home *** CD-ROM | disk | FTP | other *** search
/ Windows Game Programming for Dummies (2nd Edition) / WinGamProgFD.iso / pc / Source / GPCHAP14 / PROG14_1.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  2002-04-29  |  15.9 KB  |  630 lines

  1. // PROG14_1.CPP - DirectInput keyboard demo
  2.  
  3. // INCLUDES ///////////////////////////////////////////////
  4.  
  5. #define WIN32_LEAN_AND_MEAN  
  6. #define INITGUID
  7.  
  8. #include <windows.h>   // include important windows stuff
  9. #include <windowsx.h> 
  10. #include <mmsystem.h>
  11. #include <objbase.h>
  12. #include <iostream.h> // include important C/C++ stuff
  13. #include <conio.h>
  14. #include <stdlib.h>
  15. #include <malloc.h>
  16. #include <memory.h>
  17. #include <string.h>
  18. #include <stdarg.h>
  19. #include <stdio.h> 
  20. #include <math.h>
  21. #include <io.h>
  22. #include <fcntl.h>
  23.  
  24. #include <ddraw.h>     // directX includes
  25. #include <dinput.h> 
  26. #include "gpdumb1.h"
  27.  
  28. // DEFINES ////////////////////////////////////////////////
  29.  
  30. // defines for windows 
  31. #define WINDOW_CLASS_NAME "WINXCLASS"  // class name
  32.  
  33. #define WINDOW_WIDTH    64   // size of window
  34. #define WINDOW_HEIGHT   48
  35.  
  36. // skelaton directions
  37. #define SKELATON_EAST         0
  38. #define SKELATON_NEAST        1  
  39. #define SKELATON_NORTH        2
  40. #define SKELATON_NWEST        3
  41. #define SKELATON_WEST         4
  42. #define SKELATON_SWEST        5
  43. #define SKELATON_SOUTH        6
  44. #define SKELATON_SEAST        7
  45.  
  46. // PROTOTYPES /////////////////////////////////////////////
  47.  
  48. // game console
  49. int Game_Init(void *parms=NULL);
  50. int Game_Shutdown(void *parms=NULL);
  51. int Game_Main(void *parms=NULL);
  52.  
  53. // GLOBALS ////////////////////////////////////////////////
  54.  
  55. HWND main_window_handle = NULL; // save the window handle
  56. HINSTANCE main_instance = NULL; // save the instance
  57. char buffer[80];                // used to print text
  58.  
  59. // directinput globals
  60. LPDIRECTINPUT8       lpdi      = NULL;    // dinput object
  61. LPDIRECTINPUTDEVICE8 lpdikey   = NULL;    // dinput keyboard
  62. LPDIRECTINPUTDEVICE8 lpdimouse = NULL;    // dinput mouse
  63. LPDIRECTINPUTDEVICE8 lpdijoy   = NULL;    // dinput joystick 
  64. GUID                 joystickGUID;        // guid for main joystick
  65. char                 joyname[80];         // name of joystick
  66.  
  67. // these contain the target records for all di input packets
  68. UCHAR keyboard_state[256]; // contains keyboard state table
  69. DIMOUSESTATE mouse_state;  // contains state of mouse
  70. DIJOYSTATE joy_state;      // contains state of joystick
  71.  
  72. // demo globals
  73. BOB          skelaton;     // the player skelaton
  74.  
  75. // animation sequences for bob
  76. int skelaton_anims[8][4] = { {0,1,0,2},
  77.                              {0+4,1+4,0+4,2+4},
  78.                              {0+8,1+8,0+8,2+8},
  79.                              {0+12,1+12,0+12,2+12},
  80.                              {0+16,1+16,0+16,2+16},
  81.                              {0+20,1+20,0+20,2+20},
  82.                              {0+24,1+24,0+24,2+24},
  83.                              {0+28,1+28,0+28,2+28}, };
  84.  
  85. BOB          plasma;       // players weapon
  86.  
  87. BITMAP_IMAGE reactor;      // the background   
  88.  
  89. // PROTOTYPES //////////////////////////////////////////////
  90.  
  91. int Color_Scan(int x1, int y1, int x2, int y2, 
  92.       UCHAR scan_color, UCHAR *scan_buffer, int scan_lpitch);
  93.  
  94. // FUNCTIONS //////////////////////////////////////////////
  95.  
  96. LRESULT CALLBACK WindowProc(HWND hwnd, 
  97.                             UINT msg, 
  98.                             WPARAM wparam, 
  99.                             LPARAM lparam)
  100. {
  101. // this is the main message handler of the system
  102. PAINTSTRUCT    ps;           // used in WM_PAINT
  103. HDC            hdc;       // handle to a device context
  104.  
  105. // what is the message 
  106. switch(msg)
  107.     {    
  108.     case WM_CREATE: 
  109.         {
  110.         // do initialization stuff here
  111.         return(0);
  112.         } break;
  113.  
  114.     case WM_PAINT:
  115.          {
  116.          // start painting
  117.          hdc = BeginPaint(hwnd,&ps);
  118.  
  119.          // end painting
  120.          EndPaint(hwnd,&ps);
  121.          return(0);
  122.         } break;
  123.  
  124.     case WM_DESTROY: 
  125.         {
  126.         // kill the application            
  127.         PostQuitMessage(0);
  128.         return(0);
  129.         } break;
  130.  
  131.     default:break;
  132.  
  133.     } // end switch
  134.  
  135. // process any messages that we didn't take care of 
  136. return (DefWindowProc(hwnd, msg, wparam, lparam));
  137.  
  138. } // end WinProc
  139.  
  140. // WINMAIN ////////////////////////////////////////////////
  141.  
  142. int WINAPI WinMain(    HINSTANCE hinstance,
  143.                     HINSTANCE hprevinstance,
  144.                     LPSTR lpcmdline,
  145.                     int ncmdshow)
  146. {
  147. // this is the winmain function
  148.  
  149. WNDCLASS winclass;    // this will hold the class we create
  150. HWND     hwnd;        // generic window handle
  151. MSG         msg;        // generic message
  152. HDC      hdc;       // generic dc
  153. PAINTSTRUCT ps;     // generic paintstruct
  154.  
  155. // first fill in the window class stucture
  156. winclass.style            = CS_DBLCLKS | CS_OWNDC | 
  157.                           CS_HREDRAW | CS_VREDRAW;
  158. winclass.lpfnWndProc    = WindowProc;
  159. winclass.cbClsExtra        = 0;
  160. winclass.cbWndExtra        = 0;
  161. winclass.hInstance        = hinstance;
  162. winclass.hIcon            = LoadIcon(NULL, IDI_APPLICATION);
  163. winclass.hCursor        = LoadCursor(NULL, IDC_ARROW);
  164. winclass.hbrBackground    = (HBRUSH)GetStockObject(BLACK_BRUSH);
  165. winclass.lpszMenuName    = NULL; 
  166. winclass.lpszClassName    = WINDOW_CLASS_NAME;
  167.  
  168. // register the window class
  169. if (!RegisterClass(&winclass))
  170.     return(0);
  171.  
  172. // create the window, note the use of WS_POPUP
  173. if (!(hwnd = CreateWindow(WINDOW_CLASS_NAME, // class
  174.                           "WinX Game Console",     // title
  175.                           WS_POPUP | WS_VISIBLE,
  176.                            0,0,       // x,y
  177.                           WINDOW_WIDTH,  // width
  178.                           WINDOW_HEIGHT, // height
  179.                           NULL,       // handle to parent 
  180.                           NULL,       // handle to menu
  181.                           hinstance,// instance
  182.                           NULL)))    // creation parms
  183. return(0);
  184.  
  185. // save the window handle and instance in a global
  186. main_window_handle = hwnd;
  187. main_instance      = hinstance;
  188.  
  189. // perform all game console specific initialization
  190. Game_Init();
  191.  
  192. // enter main event loop
  193. while(1)
  194.     {
  195.     if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
  196.         { 
  197.         // test if this is a quit
  198.         if (msg.message == WM_QUIT)
  199.            break;
  200.     
  201.         // translate any accelerator keys
  202.         TranslateMessage(&msg);
  203.  
  204.         // send the message to the window proc
  205.         DispatchMessage(&msg);
  206.         } // end if
  207.     
  208.     // main game processing goes here
  209.     Game_Main();
  210.  
  211.     } // end while
  212.  
  213. // shutdown game and release all resources
  214. Game_Shutdown();
  215.  
  216. // return to Windows like this
  217. return(msg.wParam);
  218.  
  219. } // end WinMain
  220.  
  221. ///////////////////////////////////////////////////////////
  222.  
  223. int Color_Scan(int x1, int y1, int x2, int y2, 
  224.                UCHAR scan_color, UCHAR *scan_buffer, int scan_lpitch)
  225. {
  226. // this function implements a crude collision technique
  227. // based on scanning for a specific color within a rectangle
  228.  
  229. // clip rectangle
  230.  
  231. // x coords first    
  232. if (x1 >= screen_width)
  233.    x1=screen_width-1;
  234. else
  235. if (x1 < 0)
  236.    x1=0;
  237.  
  238. if (x2 >= screen_width)
  239.    x2=screen_width-1;
  240. else
  241. if (x2 < 0)
  242.    x2=0;
  243.  
  244. // now y-coords
  245. if (y1 >= screen_height)
  246.    y1=screen_height-1;
  247. else
  248. if (y1 < 0)
  249.    y1=0;
  250.  
  251. if (y2 >= screen_height)
  252.    y2=screen_height-1;
  253. else
  254. if (y2 < 0)
  255.    y2=0;
  256.  
  257. // scan the region
  258. scan_buffer +=y1*scan_lpitch;
  259.  
  260. for (int scan_y=y1; scan_y<=y2; scan_y++)
  261.     {
  262.     for (int scan_x=x1; scan_x<=x2; scan_x++)
  263.         {
  264.         if (scan_buffer[scan_x] == scan_color)
  265.             return(1);
  266.         } // end for x
  267.  
  268.     // move down a line
  269.     scan_buffer+=scan_lpitch;
  270.  
  271.     } // end for y
  272.  
  273. // return failure
  274. return(0);
  275.  
  276. } // end Color_Scan
  277.  
  278. // WINX GAME PROGRAMMING CONSOLE FUNCTIONS ////////////////
  279.  
  280. int Game_Init(void *parms)
  281. {
  282. // this function is where you do all the initialization 
  283. // for your game
  284.  
  285. int index;         // looping var
  286. char filename[80]; // used to build up files names
  287.  
  288. // set up screen dimensions
  289. screen_width = 640;
  290. screen_height = 480;
  291. screen_bpp   = 8;
  292.  
  293. // initialize directdraw
  294. DD_Init(screen_width, screen_height, screen_bpp);
  295.  
  296. // keyboard creation section ////////////////////////////////
  297.  
  298. // first create the direct input object
  299. if (DirectInput8Create(main_instance, DIRECTINPUT_VERSION, IID_IDirectInput8, (void **)&lpdi,NULL)!=DI_OK)
  300.    return(0);
  301.  
  302. // create a keyboard device  //////////////////////////////////
  303. if (lpdi->CreateDevice(GUID_SysKeyboard, &lpdikey, NULL)!=DI_OK)
  304.    return(0);
  305.  
  306. // set cooperation level
  307. if (lpdikey->SetCooperativeLevel(main_window_handle, 
  308.                  DISCL_NONEXCLUSIVE | DISCL_BACKGROUND)!=DI_OK)
  309.     return(0);
  310.  
  311. // set data format
  312. if (lpdikey->SetDataFormat(&c_dfDIKeyboard)!=DI_OK)
  313.    return(0);
  314.  
  315. // acquire the keyboard
  316. if (lpdikey->Acquire()!=DI_OK)
  317.    return(0);
  318.  
  319. ///////////////////////////////////////////////////////////
  320.  
  321. // load the background
  322. Load_Bitmap_File(&bitmap8bit, "REACTOR8.BMP");
  323.  
  324. // set the palette to background image palette
  325. Set_Palette(bitmap8bit.palette);
  326.  
  327. // create and load the reactor bitmap image
  328. Create_Bitmap(&reactor, 0,0, 640, 480);
  329. Load_Image_Bitmap(&reactor,&bitmap8bit,0,0,BITMAP_EXTRACT_MODE_ABS);
  330. Unload_Bitmap_File(&bitmap8bit);
  331.  
  332. // now let's load in all the frames for the skelaton!!!
  333.  
  334. // create skelaton bob
  335. if (!Create_BOB(&skelaton,0,0,56,72,32,
  336.            BOB_ATTR_VISIBLE | BOB_ATTR_MULTI_ANIM,DDSCAPS_SYSTEMMEMORY))
  337.    return(0);
  338.  
  339. // load the frames in 8 directions, 4 frames each
  340. // each set of frames has a walk and a fire, frame sets
  341. // are loaded in counter clockwise order looking down
  342. // from a birds eys view or the x-z plane
  343. for (int direction = 0; direction < 8; direction++)
  344.     { 
  345.     // build up file name
  346.     sprintf(filename,"SKELSP%d.BMP",direction);
  347.  
  348.     // load in new bitmap file
  349.     Load_Bitmap_File(&bitmap8bit,filename);
  350.  
  351.     Load_Frame_BOB(&skelaton,&bitmap8bit,0+direction*4,0,0,BITMAP_EXTRACT_MODE_CELL);  
  352.     Load_Frame_BOB(&skelaton,&bitmap8bit,1+direction*4,1,0,BITMAP_EXTRACT_MODE_CELL);  
  353.     Load_Frame_BOB(&skelaton,&bitmap8bit,2+direction*4,2,0,BITMAP_EXTRACT_MODE_CELL);  
  354.     Load_Frame_BOB(&skelaton,&bitmap8bit,3+direction*4,0,1,BITMAP_EXTRACT_MODE_CELL);  
  355.  
  356.     // unload the bitmap file
  357.     Unload_Bitmap_File(&bitmap8bit);
  358.  
  359.     // set the animation sequences for skelaton
  360.     Load_Animation_BOB(&skelaton,direction,4,skelaton_anims[direction]);
  361.  
  362.     } // end for direction
  363.  
  364. // set up stating state of skelaton
  365. Set_Animation_BOB(&skelaton, 0);
  366. Set_Anim_Speed_BOB(&skelaton, 4);
  367. Set_Vel_BOB(&skelaton, 0,0);
  368. Set_Pos_BOB(&skelaton, 0, 128);
  369.  
  370. // set clipping rectangle to screen extents so mouse cursor
  371. // doens't mess up at edges
  372. RECT screen_rect = {0,0,screen_width,screen_height};
  373. lpddclipper = DD_Attach_Clipper(lpddsback,1,&screen_rect);
  374.  
  375. // hide the mouse
  376. ShowCursor(FALSE);
  377.  
  378. // return success
  379. return(1);
  380.  
  381. } // end Game_Init
  382.  
  383. ///////////////////////////////////////////////////////////
  384.  
  385. int Game_Shutdown(void *parms)
  386. {
  387. // this function is where you shutdown your game and
  388. // release all resources that you allocated
  389.  
  390. // kill the reactor
  391. Destroy_Bitmap(&reactor);
  392.  
  393. // kill skelaton
  394. Destroy_BOB(&skelaton);
  395.  
  396. // release keyboard
  397. lpdikey->Unacquire();
  398. lpdikey->Release();
  399. lpdi->Release();
  400.  
  401. // shutdonw directdraw
  402. DD_Shutdown();
  403.  
  404. // return success
  405. return(1);
  406. } // end Game_Shutdown
  407.  
  408. ///////////////////////////////////////////////////////////
  409.  
  410. int Game_Main(void *parms)
  411. {
  412. // this is the workhorse of your game it will be called
  413. // continuously in real-time this is like main() in C
  414. // all the calls for you game go here!
  415.  
  416. int          index;             // looping var
  417. int          dx,dy;             // general deltas used in collision detection
  418.  
  419. static int   player_moving = 0; // tracks player motion
  420. static PALETTEENTRY glow = {0,0,0,PC_NOCOLLAPSE};  // used to animation red border
  421.  
  422. // check of user is trying to exit
  423. if (KEY_DOWN(VK_ESCAPE) || KEY_DOWN(VK_SPACE))
  424.     PostMessage(main_window_handle, WM_DESTROY,0,0);
  425.  
  426. // start the timing clock
  427. Start_Clock();
  428.  
  429. // clear the drawing surface
  430. DD_Fill_Surface(lpddsback, 0);
  431.  
  432. // lock the back buffer
  433. DD_Lock_Back_Surface();
  434.  
  435. // draw the background reactor image
  436. Draw_Bitmap(&reactor, back_buffer, back_lpitch, 0);
  437.  
  438. // unlock the back buffer
  439. DD_Unlock_Back_Surface();
  440.  
  441. // get player input
  442.  
  443. // get the keyboard data
  444. lpdikey->GetDeviceState(256, (LPVOID)keyboard_state);
  445.  
  446. // reset motion flag
  447. player_moving = 0;
  448.  
  449. // test direction of motion, this is a good example of testing the keyboard
  450. // although the code could be optimized this is more educational
  451.  
  452. if (keyboard_state[DIK_RIGHT] && keyboard_state[DIK_UP]) 
  453.    {
  454.    // move skelaton
  455.    skelaton.x+=2;
  456.    skelaton.y-=2;
  457.    dx=2; dy=-2;
  458.  
  459.    // set motion flag
  460.    player_moving = 1;
  461.  
  462.    // check animation needs to change
  463.    if (skelaton.curr_animation != SKELATON_NEAST)
  464.       Set_Animation_BOB(&skelaton,SKELATON_NEAST);
  465.  
  466.    } // end if
  467. else
  468. if (keyboard_state[DIK_LEFT] && keyboard_state[DIK_UP]) 
  469.    {
  470.    // move skelaton
  471.    skelaton.x-=2;
  472.    skelaton.y-=2;
  473.    dx=-2; dy=-2;
  474.  
  475.    // set motion flag
  476.    player_moving = 1;
  477.  
  478.    // check animation needs to change
  479.    if (skelaton.curr_animation != SKELATON_NWEST)
  480.       Set_Animation_BOB(&skelaton,SKELATON_NWEST);
  481.  
  482.    } // end if
  483. else
  484. if (keyboard_state[DIK_LEFT] && keyboard_state[DIK_DOWN]) 
  485.    {
  486.    // move skelaton
  487.    skelaton.x-=2;
  488.    skelaton.y+=2;
  489.    dx=-2; dy=2;
  490.  
  491.    // set motion flag
  492.    player_moving = 1;
  493.  
  494.    // check animation needs to change
  495.    if (skelaton.curr_animation != SKELATON_SWEST)
  496.       Set_Animation_BOB(&skelaton,SKELATON_SWEST);
  497.  
  498.    } // end if
  499. else
  500. if (keyboard_state[DIK_RIGHT] && keyboard_state[DIK_DOWN]) 
  501.    {
  502.    // move skelaton
  503.    skelaton.x+=2;
  504.    skelaton.y+=2;
  505.    dx=2; dy=2;
  506.  
  507.    // set motion flag
  508.    player_moving = 1;
  509.  
  510.    // check animation needs to change
  511.    if (skelaton.curr_animation != SKELATON_SEAST)
  512.       Set_Animation_BOB(&skelaton,SKELATON_SEAST);
  513.  
  514.    } // end if
  515. else
  516. if (keyboard_state[DIK_RIGHT]) 
  517.    {
  518.    // move skelaton
  519.    skelaton.x+=2;
  520.    dx=2; dy=0;
  521.  
  522.    // set motion flag
  523.    player_moving = 1;
  524.  
  525.    // check animation needs to change
  526.    if (skelaton.curr_animation != SKELATON_EAST)
  527.       Set_Animation_BOB(&skelaton,SKELATON_EAST);
  528.  
  529.    } // end if
  530. else
  531. if (keyboard_state[DIK_LEFT])  
  532.    {
  533.    // move skelaton
  534.    skelaton.x-=2;
  535.    dx=-2; dy=0; 
  536.    
  537.    // set motion flag
  538.    player_moving = 1;
  539.  
  540.    // check animation needs to change
  541.    if (skelaton.curr_animation != SKELATON_WEST)
  542.       Set_Animation_BOB(&skelaton,SKELATON_WEST);
  543.  
  544.    } // end if
  545. else
  546. if (keyboard_state[DIK_UP])    
  547.    {
  548.    // move skelaton
  549.    skelaton.y-=2;
  550.    dx=0; dy=-2;
  551.    
  552.    // set motion flag
  553.    player_moving = 1;
  554.  
  555.    // check animation needs to change
  556.    if (skelaton.curr_animation != SKELATON_NORTH)
  557.       Set_Animation_BOB(&skelaton,SKELATON_NORTH);
  558.  
  559.    } // end if
  560. else
  561. if (keyboard_state[DIK_DOWN])  
  562.    {
  563.    // move skelaton
  564.    skelaton.y+=2;
  565.    dx=0; dy=+2;
  566.  
  567.    // set motion flag
  568.    player_moving = 1;
  569.  
  570.    // check animation needs to change
  571.    if (skelaton.curr_animation != SKELATON_SOUTH)
  572.       Set_Animation_BOB(&skelaton,SKELATON_SOUTH);
  573.  
  574.    } // end if
  575.  
  576. // only animate if player is moving
  577. if (player_moving)
  578.    {
  579.    // animate skelaton
  580.    Animate_BOB(&skelaton);
  581.  
  582.  
  583.    // see if skelaton hit a wall
  584.    
  585.    // lock surface, so we can scan it
  586.    DD_Lock_Back_Surface();
  587.    
  588.    // call the color scanner with 29, the color of the glowing wall
  589.    // try to center the scan in the center of the object to make it 
  590.    // more realistic
  591.    if (Color_Scan(skelaton.x+16, skelaton.y+16,
  592.                   skelaton.x+skelaton.width-16, skelaton.y+skelaton.height-16,                                    
  593.                   29, back_buffer,back_lpitch))
  594.       {
  595.       // back the skelaton up along its last trajectory
  596.       skelaton.x-=dx;
  597.       skelaton.y-=dy;
  598.       } // end if
  599.    
  600.    // done, so unlock
  601.    DD_Unlock_Back_Surface();
  602.  
  603.    } // end if
  604.  
  605. // draw the skelaton
  606. Draw_BOB(&skelaton, lpddsback);
  607.  
  608. // animate green energy border
  609. glow.peGreen = rand()%256;
  610. Set_Palette_Entry(29, &glow);
  611.  
  612.  
  613. // draw some text
  614. Draw_Text_GDI("WHERE IS EVERYBODY? I HAVE A BONE TO PICK!",0,0,RGB(10,10,10),lpddsback);
  615.  
  616. Draw_Text_GDI("USE ARROW KEYS TO MOVE ME.",0,screen_height-32,RGB(10,10,10),lpddsback);
  617.  
  618. // flip the surfaces
  619. DD_Flip();
  620.  
  621. // sync to 3o fps
  622. Wait_Clock(30);
  623.  
  624.  
  625. // return success
  626. return(1);
  627.  
  628. } // end Game_Main
  629.  
  630. //////////////////////////////////////////////////////////