home *** CD-ROM | disk | FTP | other *** search
/ Windows Game Programming for Dummies (2nd Edition) / WinGamProgFD.iso / pc / Source / GPCHAP17 / PROG17_4.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  2002-05-01  |  12.8 KB  |  493 lines

  1. // PROG17_4.CPP - two mass gravity simulation
  2. // to compile make sure to include DDRAW.LIB, DSOUND.LIB,
  3. // DINPUT.LIB, DINPUT8.LIB, WINMM.LIB, and of course GPDUMB I and II files.
  4. // note: there is currently no upper limit on your velocity
  5. // since this is more realistic, so be careful not to get 
  6. // out of control
  7.  
  8. // INCLUDES ///////////////////////////////////////////////
  9.  
  10. #define WIN32_LEAN_AND_MEAN  
  11. #define INITGUID
  12.  
  13. #include <windows.h>   // include important windows stuff
  14. #include <windowsx.h> 
  15. #include <mmsystem.h>
  16. #include <iostream.h> // include important C/C++ stuff
  17. #include <conio.h>
  18. #include <stdlib.h>
  19. #include <malloc.h>
  20. #include <memory.h>
  21. #include <string.h>
  22. #include <stdarg.h>
  23. #include <stdio.h> 
  24. #include <math.h>
  25. #include <io.h>
  26. #include <fcntl.h>
  27.  
  28. #include <ddraw.h>  // directX includes
  29. #include <dsound.h>
  30. #include <dinput.h>
  31. #include "gpdumb1.h" // game library includes
  32. #include "gpdumb2.h"
  33.  
  34. // DEFINES ////////////////////////////////////////////////
  35.  
  36. // defines for windows 
  37. #define WINDOW_CLASS_NAME "WINXCLASS"  // class name
  38.  
  39. #define WINDOW_WIDTH    320            // size of window
  40. #define WINDOW_HEIGHT   240
  41.  
  42. #define FRICTION_FACTOR  (float)(0.05)  // friction of the virtual space
  43.  
  44. // these are the gravity constants, they are selected to simply work
  45. #define VIRTUAL_GRAVITY_CONSTANT     (float)0.01
  46. #define SHIP_MASS                    (float)2
  47. #define BLACK_HOLE_MASS              (float)50000
  48.  
  49. // PROTOTYPES /////////////////////////////////////////////
  50.  
  51. // game console
  52. int Game_Init(void *parms=NULL);
  53. int Game_Shutdown(void *parms=NULL);
  54. int Game_Main(void *parms=NULL);
  55.  
  56. // GLOBALS ////////////////////////////////////////////////
  57.  
  58. HWND main_window_handle   = NULL; // save the window handle
  59. HINSTANCE main_instance   = NULL; // save the instance
  60. char buffer[80];                          // used to print text
  61.  
  62. BITMAP_IMAGE background_bmp;   // holds the background
  63. BOB          ship;             // the ship
  64. BOB          black_hole;       // the gravity well
  65.  
  66. int sound_id = -1;             // general sound
  67.  
  68. // FUNCTIONS //////////////////////////////////////////////
  69.  
  70. LRESULT CALLBACK WindowProc(HWND hwnd, 
  71.                             UINT msg, 
  72.                             WPARAM wparam, 
  73.                             LPARAM lparam)
  74. {
  75. // this is the main message handler of the system
  76. PAINTSTRUCT    ps;           // used in WM_PAINT
  77. HDC            hdc;       // handle to a device context
  78.  
  79. // what is the message 
  80. switch(msg)
  81.     {    
  82.     case WM_CREATE: 
  83.         {
  84.         // do initialization stuff here
  85.         return(0);
  86.         } break;
  87.  
  88.     case WM_PAINT:
  89.          {
  90.          // start painting
  91.          hdc = BeginPaint(hwnd,&ps);
  92.  
  93.          // end painting
  94.          EndPaint(hwnd,&ps);
  95.          return(0);
  96.         } break;
  97.  
  98.     case WM_DESTROY: 
  99.         {
  100.         // kill the application            
  101.         PostQuitMessage(0);
  102.         return(0);
  103.         } break;
  104.  
  105.     default:break;
  106.  
  107.     } // end switch
  108.  
  109. // process any messages that we didn't take care of 
  110. return (DefWindowProc(hwnd, msg, wparam, lparam));
  111.  
  112. } // end WinProc
  113.  
  114. // WINMAIN ////////////////////////////////////////////////
  115.  
  116. int WINAPI WinMain(    HINSTANCE hinstance,
  117.                     HINSTANCE hprevinstance,
  118.                     LPSTR lpcmdline,
  119.                     int ncmdshow)
  120. {
  121. // this is the winmain function
  122.  
  123. WNDCLASS winclass;    // this will hold the class we create
  124. HWND     hwnd;        // generic window handle
  125. MSG         msg;        // generic message
  126. HDC      hdc;       // generic dc
  127. PAINTSTRUCT ps;     // generic paintstruct
  128.  
  129. // first fill in the window class stucture
  130. winclass.style            = CS_DBLCLKS | CS_OWNDC | 
  131.                           CS_HREDRAW | CS_VREDRAW;
  132. winclass.lpfnWndProc    = WindowProc;
  133. winclass.cbClsExtra        = 0;
  134. winclass.cbWndExtra        = 0;
  135. winclass.hInstance        = hinstance;
  136. winclass.hIcon            = LoadIcon(NULL, IDI_APPLICATION);
  137. winclass.hCursor        = LoadCursor(NULL, IDC_ARROW);
  138. winclass.hbrBackground    = (HBRUSH)GetStockObject(BLACK_BRUSH);
  139. winclass.lpszMenuName    = NULL; 
  140. winclass.lpszClassName    = WINDOW_CLASS_NAME;
  141.  
  142. // register the window class
  143. if (!RegisterClass(&winclass))
  144.     return(0);
  145.  
  146. // create the window, note the use of WS_POPUP
  147. if (!(hwnd = CreateWindow(WINDOW_CLASS_NAME, // class
  148.                           "WinX Game Console",     // title
  149.                           WS_POPUP | WS_VISIBLE,
  150.                            0,0,       // x,y
  151.                           WINDOW_WIDTH,  // width
  152.                           WINDOW_HEIGHT, // height
  153.                           NULL,       // handle to parent 
  154.                           NULL,       // handle to menu
  155.                           hinstance,// instance
  156.                           NULL)))    // creation parms
  157. return(0);
  158.  
  159. // save the window handle and instance in a global
  160. main_window_handle = hwnd;
  161. main_instance      = hinstance;
  162.  
  163. // perform all game console specific initialization
  164. Game_Init();
  165.  
  166. // enter main event loop
  167. while(1)
  168.     {
  169.     if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
  170.         { 
  171.         // test if this is a quit
  172.         if (msg.message == WM_QUIT)
  173.            break;
  174.     
  175.         // translate any accelerator keys
  176.         TranslateMessage(&msg);
  177.  
  178.         // send the message to the window proc
  179.         DispatchMessage(&msg);
  180.         } // end if
  181.     
  182.     // main game processing goes here
  183.     Game_Main();
  184.  
  185.     } // end while
  186.  
  187. // shutdown game and release all resources
  188. Game_Shutdown();
  189.  
  190. // return to Windows like this
  191. return(msg.wParam);
  192.  
  193. } // end WinMain
  194.  
  195. // WINX GAME PROGRAMMING CONSOLE FUNCTIONS ////////////////
  196.  
  197. int Game_Init(void *parms)
  198. {
  199. // this function is where you do all the initialization 
  200. // for your game
  201.  
  202. int index; // looping varsIable
  203.  
  204. char filename[80]; // used to build up filenames
  205.  
  206. // seed random number generate
  207. srand(Start_Clock());
  208.  
  209. screen_width  = 640;
  210. screen_height = 480;
  211. screen_bpp    = 8;
  212.  
  213. // start up DirectDraw (replace the parms as you desire)
  214. DD_Init(screen_width, screen_height, screen_bpp);
  215.  
  216. // load background image
  217. Load_Bitmap_File(&bitmap8bit, "GRAVSKY8.BMP");
  218. Create_Bitmap(&background_bmp,0,0,640,480);
  219. Load_Image_Bitmap(&background_bmp, &bitmap8bit,0,0,BITMAP_EXTRACT_MODE_ABS);
  220. Set_Palette(bitmap8bit.palette);
  221. Unload_Bitmap_File(&bitmap8bit);
  222.  
  223. // load the bitmaps for ship
  224. Load_Bitmap_File(&bitmap8bit, "BLAZE8.BMP");
  225.  
  226. // create bob
  227. Create_BOB(&ship,320,240,22,18,32,BOB_ATTR_MULTI_FRAME | BOB_ATTR_VISIBLE, DDSCAPS_SYSTEMMEMORY);
  228.  
  229. // well use varsI[0] to hold the direction 0..15, 0-360 degrees, clockwise
  230. ship.varsI[0] = 0; // along +x axis to start
  231.  
  232. // use varsF[0,1] for the x and y velocity
  233. ship.varsF[0] = 0;
  234. ship.varsF[1] = 0;
  235.  
  236. // use varsF[2,3] for the x and y position, we need more accuracy than ints
  237. ship.varsF[2] = ship.x;
  238. ship.varsF[3] = ship.y;
  239.  
  240. // load the frames in
  241. for (index=0; index < 32; index++)
  242.     Load_Frame_BOB(&ship, &bitmap8bit, index, index%16,index/16,BITMAP_EXTRACT_MODE_CELL);
  243.  
  244. // unload bitmap image
  245. Unload_Bitmap_File(&bitmap8bit);
  246.  
  247. // load the bitmaps for blackhole
  248. Load_Bitmap_File(&bitmap8bit, "PHOTON8.BMP");
  249.  
  250. // create bob
  251. Create_BOB(&black_hole,32+rand()%(screen_width-64),32+rand()%(screen_height-64),
  252.             44,44,7,BOB_ATTR_MULTI_FRAME | BOB_ATTR_VISIBLE, DDSCAPS_SYSTEMMEMORY);
  253.  
  254. // set animation speed
  255. Set_Anim_Speed_BOB(&black_hole,3);
  256.  
  257. // load the frames in
  258. for (index=0; index < 7; index++)
  259.     Load_Frame_BOB(&black_hole, &bitmap8bit, index, index,0,BITMAP_EXTRACT_MODE_CELL);
  260.  
  261. // unload bitmap image
  262. Unload_Bitmap_File(&bitmap8bit);
  263.  
  264. // initialize directinput
  265. DInput_Init();
  266.  
  267. // acquire the keyboard only
  268. DI_Init_Keyboard();
  269.  
  270. // initilize DirectSound
  271. DSound_Init();
  272.  
  273. // load background sounds
  274. sound_id = Load_WAV("BHOLE.WAV");
  275.  
  276. // start the sounds
  277. Play_Sound(sound_id, DSBPLAY_LOOPING);
  278.  
  279. // set clipping rectangle to screen extents so objects dont
  280. // mess up at edges
  281. RECT screen_rect = {0,0,screen_width,screen_height};
  282. lpddclipper = DD_Attach_Clipper(lpddsback,1,&screen_rect);
  283.  
  284. // hide the mouse
  285. ShowCursor(FALSE);
  286.  
  287. // return success
  288. return(1);
  289.  
  290. } // end Game_Init
  291.  
  292. ///////////////////////////////////////////////////////////
  293.  
  294. int Game_Shutdown(void *parms)
  295. {
  296. // this function is where you shutdown your game and
  297. // release all resources that you allocated
  298.  
  299. // shut everything down
  300.  
  301. // kill all the bobs
  302. Destroy_BOBX(&ship);
  303. Destroy_BOBX(&black_hole);
  304.  
  305. // shutdown directdraw last
  306. DD_Shutdown();
  307.  
  308. // now directsound
  309. Stop_All_Sounds();
  310. DSound_Shutdown();
  311.  
  312. // shut down directinput
  313. DInput_Shutdown();
  314.  
  315. // return success
  316. return(1);
  317.  
  318. } // end Game_Shutdown
  319.  
  320. //////////////////////////////////////////////////////////
  321.  
  322. int Game_Main(void *parms)
  323. {
  324. // this is the workhorse of your game it will be called
  325. // continuously in real-time this is like main() in C
  326. // all the calls for you game go here!
  327.  
  328. int index; // looping var
  329.  
  330. // start the timing clock
  331. Start_Clock();
  332.  
  333. // clear the drawing surface
  334. DD_Fill_Surface(lpddsback, 0);
  335.  
  336. // lock back buffer and copy background into it
  337. DD_Lock_Back_Surface();
  338.  
  339. // draw background
  340. Draw_Bitmap(&background_bmp, back_buffer, back_lpitch,0);
  341.  
  342. // unlock back surface
  343. DD_Unlock_Back_Surface();
  344.  
  345. // read keyboard
  346. DI_Read_Keyboard();
  347.  
  348.  
  349. // check the player controls
  350.  
  351. // is the player turning right or left?
  352. if (keyboard_state[DIK_RIGHT])
  353.    {
  354.     // there are 16 possible positions for the ship to point in
  355.     if (++ship.varsI[0] >= 16)
  356.         ship.varsI[0] = 0;
  357.    } // end if
  358. else
  359. if (keyboard_state[DIK_LEFT])
  360.    {
  361.     // there are 16 possible positions for the ship to point in
  362.     if (--ship.varsI[0] < 0)
  363.         ship.varsI[0] = 15;
  364.    } // end if
  365.  
  366. // now test for forward thrust
  367. if (keyboard_state[DIK_UP])
  368.     {
  369.     // thrust ship in current direction
  370.     
  371.     float rad_angle = (float)ship.varsI[0]*(float)3.14159/(float)8;
  372.     float xv = cos(rad_angle);
  373.     float yv = sin(rad_angle);
  374.  
  375.     ship.varsF[0]+=xv;
  376.     ship.varsF[1]+=yv;
  377.  
  378.     // animate the ship
  379.     ship.curr_frame = ship.varsI[0]+16*(rand()%2);
  380.  
  381.     } // end if
  382. else // show non thrust version
  383.    ship.curr_frame = ship.varsI[0];  
  384.  
  385. // move ship
  386. ship.varsF[2]+=ship.varsF[0];
  387. ship.varsF[3]+=ship.varsF[1];
  388.  
  389. // always apply friction in direction opposite current trajectory
  390. float fx = -ship.varsF[0];
  391. float fy = -ship.varsF[1];
  392. float length_f = sqrt(fx*fx+fy*fy); // normally we would avoid square root at all costs!
  393.  
  394. // compute the frictional resitance
  395.  
  396. if (fabs(length_f) > 0.1)
  397.     { 
  398.     fx = FRICTION_FACTOR*fx/length_f;
  399.     fy = FRICTION_FACTOR*fy/length_f;
  400.     } // end if
  401. else
  402.     fx=fy=0;
  403.  
  404. // now apply friction to forward velocity
  405. ship.varsF[0]+=fx;
  406. ship.varsF[1]+=fy;
  407.  
  408. ////////////////////////////////////////////////////////////////////
  409.  
  410. // gravity calculation section
  411.  
  412. // step 1: compute vector from black hole to ship, note that the centers
  413. // of each object are used
  414. float grav_x = (black_hole.x + black_hole.width/2)  - (ship.x + ship.width/2);
  415. float grav_y = (black_hole.y + black_hole.height/2) - (ship.y + ship.height/2);
  416. float radius_squared = grav_x*grav_x + grav_y*grav_y; // equal to radius squared
  417. float length_grav = sqrt(radius_squared);
  418.  
  419. // step 2: normalize the length of the vector to 1.0
  420. grav_x = grav_x/length_grav;
  421. grav_y = grav_y/length_grav;
  422.  
  423. // step 3: compute the gravity force
  424. float grav_force = (VIRTUAL_GRAVITY_CONSTANT) * (SHIP_MASS * BLACK_HOLE_MASS) / radius_squared;
  425.  
  426. // step 4: apply gforce in the direction of grav_x, grav_y with the magnitude of grav_force
  427. ship.varsF[0]+=grav_x*grav_force;
  428. ship.varsF[1]+=grav_y*grav_force;
  429.  
  430. ////////////////////////////////////////////////////////////////////
  431.  
  432. // test if ship is off screen
  433. if (ship.varsF[2] > screen_width)
  434.    ship.varsF[2] = -ship.width;
  435. else
  436. if (ship.varsF[2] < -ship.width)
  437.    ship.varsF[2] = screen_width;
  438.  
  439. if (ship.varsF[3] > screen_height)
  440.    ship.varsF[3] = -ship.height;
  441. else
  442. if (ship.varsF[3] < -ship.height)
  443.    ship.varsF[3] = screen_height;
  444.  
  445. // animate the black hole
  446. Animate_BOB(&black_hole);
  447.  
  448. // draw the black hole
  449. Draw_BOB(&black_hole, lpddsback);
  450.  
  451. // copy floating point position to bob x,y
  452. ship.x = ship.varsF[2];
  453. ship.y = ship.varsF[3];
  454.  
  455. // draw the ship
  456. Draw_BOB(&ship,lpddsback);
  457.  
  458. // draw the title
  459. Draw_Text_GDI("GRAVITY MASS DEMO - Use Arrows to Control Ship.",10, 10,RGB(0,255,255), lpddsback);
  460.  
  461. sprintf(buffer,"Friction: X=%f, Y=%f",fx, fy);
  462. Draw_Text_GDI(buffer,10,420,RGB(0,255,0), lpddsback);
  463.  
  464. sprintf(buffer,"Velocity: X=%f, Y=%f",ship.varsF[0], ship.varsF[1]);
  465. Draw_Text_GDI(buffer,10,440,RGB(0,255,0), lpddsback);
  466.  
  467. sprintf(buffer,"Gravity: X=%f, Y=%f",ship.varsF[2], ship.varsF[3]);
  468. Draw_Text_GDI(buffer,10,460,RGB(0,255,0), lpddsback);
  469.  
  470. // flip the surfaces
  471. DD_Flip();
  472.  
  473. // sync to 30 fps = 1/30sec = 33 ms
  474. Wait_Clock(33);
  475.  
  476. // check of user is trying to exit
  477. if (KEY_DOWN(VK_ESCAPE) || keyboard_state[DIK_ESCAPE])
  478.     {
  479.     PostMessage(main_window_handle, WM_DESTROY,0,0);
  480.  
  481.     // stop all sounds
  482.     Stop_All_Sounds();
  483.  
  484.     // do a screen transition
  485.     Screen_Transitions(SCREEN_DARKNESS,NULL,0);
  486.     } // end if
  487.  
  488. // return success
  489. return(1);
  490.  
  491. } // end Game_Main
  492.  
  493. //////////////////////////////////////////////////////////