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

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