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

  1. // PROG17_4_16b.CPP - 16-bit version, 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    = 16;
  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(&bitmap16bit, "GRAVSKY16.BMP");
  218. Create_Bitmap16(&background_bmp,0,0,640,480);
  219. Load_Image_Bitmap16(&background_bmp, &bitmap16bit,0,0,BITMAP_EXTRACT_MODE_ABS);
  220. Unload_Bitmap_File(&bitmap16bit);
  221.  
  222. // load the bitmaps for ship
  223. Load_Bitmap_File(&bitmap16bit, "BLAZE16.BMP");
  224.  
  225. // create bob
  226. Create_BOB16(&ship,320,240,22,18,32,BOB_ATTR_MULTI_FRAME | BOB_ATTR_VISIBLE, DDSCAPS_SYSTEMMEMORY);
  227.  
  228. // well use varsI[0] to hold the direction 0..15, 0-360 degrees, clockwise
  229. ship.varsI[0] = 0; // along +x axis to start
  230.  
  231. // use varsF[0,1] for the x and y velocity
  232. ship.varsF[0] = 0;
  233. ship.varsF[1] = 0;
  234.  
  235. // use varsF[2,3] for the x and y position, we need more accuracy than ints
  236. ship.varsF[2] = ship.x;
  237. ship.varsF[3] = ship.y;
  238.  
  239. // load the frames in
  240. for (index=0; index < 32; index++)
  241.     Load_Frame_BOB16(&ship, &bitmap16bit, index, index%16,index/16,BITMAP_EXTRACT_MODE_CELL);
  242.  
  243. // unload bitmap image
  244. Unload_Bitmap_File(&bitmap16bit);
  245.  
  246. // load the bitmaps for blackhole
  247. Load_Bitmap_File(&bitmap16bit, "PHOTON16.BMP");
  248.  
  249. // create bob
  250. Create_BOB16(&black_hole,32+rand()%(screen_width-64),32+rand()%(screen_height-64),
  251.             44,44,7,BOB_ATTR_MULTI_FRAME | BOB_ATTR_VISIBLE, DDSCAPS_SYSTEMMEMORY);
  252.  
  253. // set animation speed
  254. Set_Anim_Speed_BOB16(&black_hole,3);
  255.  
  256. // load the frames in
  257. for (index=0; index < 7; index++)
  258.     Load_Frame_BOB16(&black_hole, &bitmap16bit, index, index,0,BITMAP_EXTRACT_MODE_CELL);
  259.  
  260. // unload bitmap image
  261. Unload_Bitmap_File(&bitmap16bit);
  262.  
  263. // initialize directinput
  264. DInput_Init();
  265.  
  266. // acquire the keyboard only
  267. DI_Init_Keyboard();
  268.  
  269. // initilize DirectSound
  270. DSound_Init();
  271.  
  272. // load background sounds
  273. sound_id = Load_WAV("BHOLE.WAV");
  274.  
  275. // start the sounds
  276. Play_Sound(sound_id, DSBPLAY_LOOPING);
  277.  
  278. // set clipping rectangle to screen extents so objects dont
  279. // mess up at edges
  280. RECT screen_rect = {0,0,screen_width,screen_height};
  281. lpddclipper = DD_Attach_Clipper(lpddsback,1,&screen_rect);
  282.  
  283. // hide the mouse
  284. ShowCursor(FALSE);
  285.  
  286. // return success
  287. return(1);
  288.  
  289. } // end Game_Init
  290.  
  291. ///////////////////////////////////////////////////////////
  292.  
  293. int Game_Shutdown(void *parms)
  294. {
  295. // this function is where you shutdown your game and
  296. // release all resources that you allocated
  297.  
  298. // shut everything down
  299.  
  300. // kill all the bobs
  301. Destroy_BOBX(&ship);
  302. Destroy_BOBX(&black_hole);
  303.  
  304. // shutdown directdraw last
  305. DD_Shutdown();
  306.  
  307. // now directsound
  308. Stop_All_Sounds();
  309. DSound_Shutdown();
  310.  
  311. // shut down directinput
  312. DInput_Shutdown();
  313.  
  314. // return success
  315. return(1);
  316.  
  317. } // end Game_Shutdown
  318.  
  319. //////////////////////////////////////////////////////////
  320.  
  321. int Game_Main(void *parms)
  322. {
  323. // this is the workhorse of your game it will be called
  324. // continuously in real-time this is like main() in C
  325. // all the calls for you game go here!
  326.  
  327. int index; // looping var
  328.  
  329. // start the timing clock
  330. Start_Clock();
  331.  
  332. // clear the drawing surface
  333. DD_Fill_Surface(lpddsback, 0);
  334.  
  335. // lock back buffer and copy background into it
  336. DD_Lock_Back_Surface();
  337.  
  338. // draw background
  339. Draw_Bitmap16(&background_bmp, back_buffer, back_lpitch,0);
  340.  
  341. // unlock back surface
  342. DD_Unlock_Back_Surface();
  343.  
  344. // read keyboard
  345. DI_Read_Keyboard();
  346.  
  347.  
  348. // check the player controls
  349.  
  350. // is the player turning right or left?
  351. if (keyboard_state[DIK_RIGHT])
  352.    {
  353.     // there are 16 possible positions for the ship to point in
  354.     if (++ship.varsI[0] >= 16)
  355.         ship.varsI[0] = 0;
  356.    } // end if
  357. else
  358. if (keyboard_state[DIK_LEFT])
  359.    {
  360.     // there are 16 possible positions for the ship to point in
  361.     if (--ship.varsI[0] < 0)
  362.         ship.varsI[0] = 15;
  363.    } // end if
  364.  
  365. // now test for forward thrust
  366. if (keyboard_state[DIK_UP])
  367.     {
  368.     // thrust ship in current direction
  369.     
  370.     float rad_angle = (float)ship.varsI[0]*(float)3.14159/(float)8;
  371.     float xv = cos(rad_angle);
  372.     float yv = sin(rad_angle);
  373.  
  374.     ship.varsF[0]+=xv;
  375.     ship.varsF[1]+=yv;
  376.  
  377.     // animate the ship
  378.     ship.curr_frame = ship.varsI[0]+16*(rand()%2);
  379.  
  380.     } // end if
  381. else // show non thrust version
  382.    ship.curr_frame = ship.varsI[0];  
  383.  
  384. // move ship
  385. ship.varsF[2]+=ship.varsF[0];
  386. ship.varsF[3]+=ship.varsF[1];
  387.  
  388. // always apply friction in direction opposite current trajectory
  389. float fx = -ship.varsF[0];
  390. float fy = -ship.varsF[1];
  391. float length_f = sqrt(fx*fx+fy*fy); // normally we would avoid square root at all costs!
  392.  
  393. // compute the frictional resitance
  394.  
  395. if (fabs(length_f) > 0.1)
  396.     { 
  397.     fx = FRICTION_FACTOR*fx/length_f;
  398.     fy = FRICTION_FACTOR*fy/length_f;
  399.     } // end if
  400. else
  401.     fx=fy=0;
  402.  
  403. // now apply friction to forward velocity
  404. ship.varsF[0]+=fx;
  405. ship.varsF[1]+=fy;
  406.  
  407. ////////////////////////////////////////////////////////////////////
  408.  
  409. // gravity calculation section
  410.  
  411. // step 1: compute vector from black hole to ship, note that the centers
  412. // of each object are used
  413. float grav_x = (black_hole.x + black_hole.width/2)  - (ship.x + ship.width/2);
  414. float grav_y = (black_hole.y + black_hole.height/2) - (ship.y + ship.height/2);
  415. float radius_squared = grav_x*grav_x + grav_y*grav_y; // equal to radius squared
  416. float length_grav = sqrt(radius_squared);
  417.  
  418. // step 2: normalize the length of the vector to 1.0
  419. grav_x = grav_x/length_grav;
  420. grav_y = grav_y/length_grav;
  421.  
  422. // step 3: compute the gravity force
  423. float grav_force = (VIRTUAL_GRAVITY_CONSTANT) * (SHIP_MASS * BLACK_HOLE_MASS) / radius_squared;
  424.  
  425. // step 4: apply gforce in the direction of grav_x, grav_y with the magnitude of grav_force
  426. ship.varsF[0]+=grav_x*grav_force;
  427. ship.varsF[1]+=grav_y*grav_force;
  428.  
  429. ////////////////////////////////////////////////////////////////////
  430.  
  431. // test if ship is off screen
  432. if (ship.varsF[2] > screen_width)
  433.    ship.varsF[2] = -ship.width;
  434. else
  435. if (ship.varsF[2] < -ship.width)
  436.    ship.varsF[2] = screen_width;
  437.  
  438. if (ship.varsF[3] > screen_height)
  439.    ship.varsF[3] = -ship.height;
  440. else
  441. if (ship.varsF[3] < -ship.height)
  442.    ship.varsF[3] = screen_height;
  443.  
  444. // animate the black hole
  445. Animate_BOB16(&black_hole);
  446.  
  447. // draw the black hole
  448. Draw_BOB16(&black_hole, lpddsback);
  449.  
  450. // copy floating point position to bob x,y
  451. ship.x = ship.varsF[2];
  452. ship.y = ship.varsF[3];
  453.  
  454. // draw the ship
  455. Draw_BOB16(&ship,lpddsback);
  456.  
  457. // draw the title
  458. Draw_Text_GDI("GRAVITY MASS DEMO - Use Arrows to Control Ship.",10, 10,RGB(0,255,255), lpddsback);
  459.  
  460. sprintf(buffer,"Friction: X=%f, Y=%f",fx, fy);
  461. Draw_Text_GDI(buffer,10,420,RGB(0,255,0), lpddsback);
  462.  
  463. sprintf(buffer,"Velocity: X=%f, Y=%f",ship.varsF[0], ship.varsF[1]);
  464. Draw_Text_GDI(buffer,10,440,RGB(0,255,0), lpddsback);
  465.  
  466. sprintf(buffer,"Gravity: X=%f, Y=%f",ship.varsF[2], ship.varsF[3]);
  467. Draw_Text_GDI(buffer,10,460,RGB(0,255,0), lpddsback);
  468.  
  469. // flip the surfaces
  470. DD_Flip();
  471.  
  472. // sync to 30 fps = 1/30sec = 33 ms
  473. Wait_Clock(33);
  474.  
  475. // check of user is trying to exit
  476. if (KEY_DOWN(VK_ESCAPE) || keyboard_state[DIK_ESCAPE])
  477.     {
  478.     PostMessage(main_window_handle, WM_DESTROY,0,0);
  479.  
  480.     // stop all sounds
  481.     Stop_All_Sounds();
  482.     } // end if
  483.  
  484. // return success
  485. return(1);
  486.  
  487. } // end Game_Main
  488.  
  489. //////////////////////////////////////////////////////////