home *** CD-ROM | disk | FTP | other *** search
/ Cutting-Edge 3D Game Programming with C++ / CE3DC++.ISO / BOOK / CHAP14 / BLEEDING.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1996-05-28  |  12.2 KB  |  418 lines

  1. //
  2. // File name: Bleeding.CPP
  3. //
  4. // Description: The main file for a simple 3D game
  5. //
  6. // Author: John De Goes
  7. //
  8. // Project: Cutting Edge 3D Game Programming
  9. //
  10.  
  11. // ------------------------------------------------------------
  12. // | Global include files:                                    |
  13. // ------------------------------------------------------------
  14.  
  15. #include <Dos.H>
  16. #include <Math.H>
  17. #include <Conio.H>
  18. #include <Time.H>
  19. #include <Stdio.H>
  20. #include <Windows.H>
  21. #include <Iostream.H>
  22.  
  23. // ------------------------------------------------------------
  24. // | Local include files:                                     |
  25. // ------------------------------------------------------------
  26.  
  27. #include "TextType.HPP"
  28. #include "3Dclass.HPP"
  29. #include "LineType.HPP"
  30. #include "PalShade.HPP"
  31. #include "Monster.HPP"
  32. #include "FastWin.HPP"
  33.  
  34. #include "Bleeding.RH"
  35.  
  36. // ------------------------------------------------------------
  37. // | Global variables/constants:                              |
  38. // ------------------------------------------------------------
  39.  
  40. LRESULT CALLBACK WndProc ( HWND hWnd, unsigned int iMessage,
  41.                           unsigned int wParam, LONG lParam );
  42.  
  43. HANDLE ThisInstance;
  44. long RightButton = FALSE, LeftButton = FALSE, 
  45.      Keys, Dir, Mag;
  46. BOOL Running = TRUE;
  47.  
  48. const long SCREEN_WIDTH = 320;
  49. const long SCREEN_HEIGHT = 200;
  50.  
  51. // ------------------------------------------------------------
  52. // | Local structs/classes:                                   |
  53. // ------------------------------------------------------------
  54.  
  55. struct View {
  56. int XRot, YRot, ZRot;
  57. float XPos, YPos, ZPos;
  58. View () { XRot = YRot = ZRot = 0;
  59.           XPos = YPos = ZPos = 0.0F; }
  60. void Clear () { XRot = YRot = ZRot = 0;
  61.                 XPos = YPos = ZPos = 0.0F; }
  62. };
  63.  
  64. // ------------------------------------------------------------
  65. // | Function section:                                        |
  66. // ------------------------------------------------------------
  67.  
  68. int InitZBuffer ()
  69.   {
  70.   // Allocate memory for Z-buffer:
  71.   if ( ( ZBuffer = new long [ 64000 ] ) == 0 )
  72.      return 0;
  73.   return 1;
  74.   }
  75.  
  76. int DestZBuffer ()
  77.   {
  78.   // Deallocate Z-buffer's memory:
  79.   delete [] ZBuffer;
  80.   if ( ZBuffer )
  81.      return 0;
  82.   return 1;
  83.   }
  84.  
  85. void ClearBuffer ()
  86.    {
  87.    // Clear the Z-buffer:
  88.    long *ZPtr = ZBuffer;
  89.    for ( unsigned int Index = 0; Index < 6400; Index++ )
  90.        {
  91.        *ZPtr++ = 0;
  92.        *ZPtr++ = 0;
  93.  
  94.        *ZPtr++ = 0;
  95.        *ZPtr++ = 0;
  96.  
  97.        *ZPtr++ = 0;
  98.        *ZPtr++ = 0;
  99.  
  100.        *ZPtr++ = 0;
  101.        *ZPtr++ = 0;
  102.  
  103.        *ZPtr++ = 0;
  104.        *ZPtr++ = 0;
  105.        }
  106.    }
  107.  
  108.  
  109. // ------------------------------------------------------------
  110. // | Program entry:                                           |
  111. // ------------------------------------------------------------
  112.  
  113. int WINAPI WinMain ( HANDLE hInstance, HANDLE hPrevInstance,
  114.             LPSTR lpszCmdParam, int nCmdShow )
  115.  
  116.   {
  117.   hPrevInstance; lpszCmdParam;
  118.   ThisInstance = hInstance;
  119.   HWND hWnd;
  120.   MSG Message;
  121.   WNDCLASS WndClass;
  122.   Matrix3D M, Copy; View V;
  123.   unsigned char *VidBuf;
  124.   Monster Mon ( 0.0, 400.0, 2000.0, "Mon.INI", Monster::ASCII );
  125.   long MaxWait, BackC, FrameNum = 0, OldXRot = 0,
  126.        Looking = FALSE, FrameCount = 0, NoSound = 0;
  127.   ZTrans = 0;
  128.   FastWin MyWin;
  129.  
  130.   // Randomize the timer for sound events:
  131.   randomize ();
  132.  
  133.   // Allocate memory for a panel object:
  134.   PanelObject *World = new PanelObject;
  135.  
  136.   // Allocate memory for Z-buffer:
  137.   InitZBuffer ();
  138.  
  139.   // Read the panel data:
  140.   World->ReadBIN ( "Test.BIN" );
  141.  
  142.   // Read -- if possible -- the texture data:
  143.   if ( World->ReadText ( "Text.BT" ) == FALSE )
  144.      {
  145.      if ( TextDat.LoadINI ( "Text.INI" ) == FALSE )
  146.         {
  147.         delete World;
  148.         return 0;
  149.         }
  150.      // Initialize default texture coords:
  151.      World->InitDefText ();
  152.      }
  153.   // Read -- if possible -- the shade table:
  154.   if ( TextShade.LoadTable ( "Shade.TAB" ) == FALSE )
  155.      {
  156.      // Generate a palette that fades to white:
  157.      TextShade.GenTable ( 150.0F, 150.0F, 150.0F,
  158.                           TextDat.TMap [ 0 ].Palette );
  159.      TextShade.SaveTable ( "Shade.TAB" );
  160.      }
  161.  
  162.   MyWin.Init ( 320, 200, TextDat.TMap [ 0 ].Palette );
  163.   VidBuf = ( unsigned char * ) MyWin;
  164.  
  165.   // Raise the viewer and move him/her forward:
  166.   M.Initialize ();
  167.   M.Translate ( 0, -700, -500 );
  168.   ClearBuffer ();
  169.   World->Display ( M, VidBuf );
  170.   MaxWait = ( long ) pow ( 2, 31 - ZSTEP_PREC  );
  171.  
  172.   // Calculate the background color (a shade of whitish-gray):
  173.   BackC = GetColor ( 150, 150, 150, TextDat.TMap [ 0 ].Palette );
  174.  
  175.   WndClass.cbClsExtra = 0;
  176.   WndClass.cbWndExtra = 0;
  177.   WndClass.hbrBackground = GetStockObject ( GRAY_BRUSH );
  178.   WndClass.hCursor =  LoadCursor ( NULL, IDC_ARROW );
  179.   WndClass.hIcon = LoadIcon ( hInstance, NULL );
  180.   WndClass.hInstance = hInstance;
  181.   WndClass.lpfnWndProc = WndProc;
  182.   WndClass.lpszClassName = "BLEEDING";
  183.   WndClass.lpszMenuName = ( const char * ) MENU_1;
  184.   WndClass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
  185.  
  186.   if ( !RegisterClass ( &WndClass ) )
  187.      return 0;           
  188.  
  189.   hWnd = CreateWindow ( "BLEEDING",             // class name
  190.                         "The Bleeding Edge Of 3D Game Programming",  // Caption
  191.                         WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU,// Style
  192.                         CW_USEDEFAULT,           // x position
  193.                         CW_USEDEFAULT,           // y position
  194.                         320,                     // cx - size
  195.                         240,                     // cy - size
  196.                         NULL,                    // Parent window
  197.                         NULL,                    // Menu
  198.                         hInstance,               // Program Instance
  199.                         NULL );                  // Parameters
  200.  
  201.   ShowWindow ( hWnd, nCmdShow );
  202.  
  203.   MyWin.Colors ();
  204.  
  205.   while ( Running )
  206.         {
  207.         // Process frame:
  208.         if ( LeftButton == TRUE )
  209.            {
  210.            if ( Dir < 0 )
  211.               {
  212.               V.YRot = fabs ( Dir ) / 10.0;
  213.               }
  214.            else {
  215.                 V.YRot = -fabs ( Dir ) / 10.0;
  216.                 }
  217.            if ( Mag < 0 )
  218.               {
  219.               V.ZPos -= fabs ( Mag ) / 5.0F;
  220.               }
  221.            else {
  222.                 V.ZPos += fabs ( Mag ) / 5.0F;
  223.                 }
  224.            }
  225.         if ( RightButton == TRUE )
  226.            {
  227.            V.ZRot = float ( Dir );
  228.            V.XRot = -float ( Mag );
  229.            }
  230.  
  231.         if ( V.XRot != 0 )
  232.            {
  233.            if ( !Looking )
  234.               {
  235.               Looking = TRUE;
  236.               Copy = M;
  237.               }
  238.            M.Rotate ( OldXRot, 0, 0 );
  239.            M.Rotate ( -V.XRot, 0, 0 );
  240.            OldXRot = V.XRot;
  241.            }
  242.         else if ( RightButton == FALSE ) 
  243.            {
  244.            // Level the player by using matrix copy:
  245.            if ( Looking == TRUE )
  246.               {
  247.               M = Copy;
  248.               Looking = FALSE;
  249.               }
  250.  
  251.            // Simulate gravity:
  252.            V.YPos = -100.0F;
  253.  
  254.            // Perform collision detection:
  255.            World->Collide ( V.XPos, V.YPos, V.ZPos, 100.0F );
  256.  
  257.            // Update the world:
  258.            M.Translate ( -V.XPos, -V.YPos, -V.ZPos );
  259.            M.Rotate ( 0, -V.YRot, 0 );
  260.  
  261.            OldXRot = 0;
  262.            }
  263.  
  264.         V.Clear ();
  265.  
  266.         // Move the monster:
  267.         Mon.MoveToward ( 0.0F, -150.0F, 0.0F, 100.0F, M );
  268.  
  269.         // Change (if necessary) to the next monster frame:
  270.         if ( ( FrameCount % 4 ) == 0 )
  271.            {
  272.            ++FrameNum;
  273.            if ( Mon.Dist () > 900.0F )
  274.               {
  275.               if ( FrameNum > 8 )
  276.                  FrameNum = 0;
  277.               }
  278.            else {
  279.                 if ( Mon.Dist () < 500 )
  280.                    {
  281.                    if ( !NoSound )
  282.                       {
  283.                       if ( random ( 100 ) >= 50 )
  284.                          sndPlaySound ( "Pain1.WAV", SND_ASYNC    );
  285.                       else sndPlaySound ( "Pain2.WAV", SND_ASYNC );
  286.                       NoSound = 20;
  287.                       }
  288.                    }
  289.                 if ( FrameNum > 11 )
  290.                    FrameNum = 9;
  291.                 }
  292.            if ( NoSound > 0 )
  293.               --NoSound;
  294.            Mon = FrameNum;
  295.            }
  296.  
  297.         setmem ( VidBuf, 64000, BackC );
  298.  
  299.         // Clear the Z-buffer (if necessary):
  300.         ZTrans += ( 1 << ZSTEP_PREC );
  301.         if ( ( FrameCount % MaxWait ) == 0 )
  302.            {
  303.            ZTrans = 0;
  304.            ClearBuffer ();
  305.            }
  306.  
  307.         World->Display ( M, VidBuf );
  308.         Mon.Show ( M, VidBuf );
  309.  
  310.         MyWin.Show ();
  311.  
  312.         if ( PeekMessage ( &Message, hWnd, 0, 0, PM_NOREMOVE ) == TRUE )
  313.            {
  314.            Running = GetMessage ( &Message, hWnd, 0, 0 );
  315.            TranslateMessage ( &Message );
  316.            DispatchMessage ( &Message );
  317.            }
  318.  
  319.         ++FrameCount;
  320.         }
  321.  
  322.   // Destroy the Z buffer:
  323.   DestZBuffer ();
  324.  
  325.   // Save the texture data:
  326.   World->WriteText ( "Text.BT" );
  327.  
  328.   // Deallocate memory for panel object:
  329.   delete World;
  330.  
  331.   return Message.wParam;
  332.   }
  333.  
  334. LRESULT CALLBACK WndProc ( HWND hWnd, unsigned int iMessage,
  335.                           unsigned int wParam, LONG lParam )
  336.    {
  337.    float XPos, YPos;
  338.    switch ( iMessage )
  339.           {
  340.           case ( WM_COMMAND ):
  341.                {
  342.                switch ( LOWORD ( wParam ) )
  343.                       {
  344.                       case ( CM_FILE_EXIT ):
  345.                            {
  346.                            Running = FALSE;
  347.                            break;
  348.                            }
  349.                       }
  350.                break;
  351.                }
  352.           case ( WM_LBUTTONUP ):
  353.                {
  354.                ReleaseCapture ();
  355.                LeftButton = FALSE;
  356.                break;
  357.                }
  358.           case ( WM_LBUTTONDOWN ):
  359.                {
  360.                SetCapture ( hWnd );
  361.                LeftButton = TRUE; RightButton = FALSE;
  362.                Keys = wParam; Keys;       // key flags                      
  363.                XPos = float ( ( short int ) ( LOWORD ( lParam ) ) );
  364.                YPos = float ( ( short int ) ( HIWORD ( lParam ) ) );
  365.                Dir  = ( SCREEN_WIDTH / 2 )  - XPos;
  366.                Mag  = ( SCREEN_HEIGHT / 2 ) - YPos;
  367.                break;
  368.                }
  369.           case ( WM_RBUTTONUP ):
  370.                {
  371.                ReleaseCapture ();
  372.                RightButton = FALSE;
  373.                break;
  374.                }
  375.           case ( WM_RBUTTONDOWN ):
  376.                {
  377.                SetCapture ( hWnd );
  378.                RightButton = TRUE; LeftButton = FALSE;
  379.                Keys = wParam; Keys;
  380.                XPos = float ( ( short int ) ( LOWORD ( lParam ) ) );
  381.                YPos = float ( ( short int ) ( HIWORD ( lParam ) ) );
  382.                Dir  = ( SCREEN_WIDTH / 2 )  - XPos;
  383.                Mag  = ( SCREEN_HEIGHT / 2 ) - YPos;
  384.                break;
  385.                }
  386.           case ( WM_MOUSEMOVE ):
  387.                {
  388.                if ( LeftButton == TRUE )
  389.                   {
  390.                   Keys = wParam; Keys;       // key flags                      
  391.                   XPos = float ( ( short int ) ( LOWORD ( lParam ) ) );
  392.                   YPos = float ( ( short int ) ( HIWORD ( lParam ) ) );
  393.                   Dir  = ( SCREEN_WIDTH / 2 )  - XPos;
  394.                   Mag  = ( SCREEN_HEIGHT / 2 ) - YPos;
  395.                   }
  396.                if ( RightButton == TRUE )
  397.                   {
  398.                   Keys = wParam; Keys;
  399.                   XPos = float ( ( short int ) ( LOWORD ( lParam ) ) );
  400.                   YPos = float ( ( short int ) ( HIWORD ( lParam ) ) );
  401.                   Dir  = ( SCREEN_WIDTH / 2 )  - XPos;
  402.                   Mag  = ( SCREEN_HEIGHT / 2 ) - YPos;
  403.                   break;
  404.                   }
  405.                break;
  406.                }
  407.           case ( WM_DESTROY ):
  408.                {
  409.                Running = FALSE;
  410.                break;
  411.                }
  412.           default:
  413.                  return DefWindowProc ( hWnd, iMessage, wParam,
  414.                                       lParam );
  415.           }
  416.    return 0;
  417.    }
  418.