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

  1. // PROG14_2.CPP - DirectInput mouse 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 <iostream.h> // include important C/C++ stuff
  12. #include <conio.h>
  13. #include <objbase.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"   // make sure to include GPDUMB1.CPP in the project
  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. #define BUTTON_SPRAY    0    // defines for each button
  37. #define BUTTON_PENCIL   1
  38. #define BUTTON_ERASE    2
  39. #define BUTTON_EXIT     3
  40.  
  41. // PROTOTYPES /////////////////////////////////////////////
  42.  
  43. // game console
  44. int Game_Init(void *parms=NULL);
  45. int Game_Shutdown(void *parms=NULL);
  46. int Game_Main(void *parms=NULL);
  47.  
  48. // GLOBALS ////////////////////////////////////////////////
  49.  
  50. HWND main_window_handle = NULL; // save the window handle
  51. HINSTANCE main_instance = NULL; // save the instance
  52. char buffer[80];                // used to print text
  53.  
  54. // directinput globals
  55. LPDIRECTINPUT8       lpdi      = NULL;    // dinput object
  56. LPDIRECTINPUTDEVICE8 lpdikey   = NULL;    // dinput keyboard
  57. LPDIRECTINPUTDEVICE8 lpdimouse = NULL;    // dinput mouse
  58. LPDIRECTINPUTDEVICE8 lpdijoy   = NULL;    // dinput joystick 
  59. GUID                 joystickGUID;        // guid for main joystick
  60. char                 joyname[80];         // name of joystick
  61.  
  62. // these contain the target records for all di input packets
  63. UCHAR keyboard_state[256]; // contains keyboard state table
  64. DIMOUSESTATE mouse_state;  // contains state of mouse
  65. DIJOYSTATE joy_state;      // contains state of joystick
  66.  
  67. // demo globals
  68. BOB          buttons,           // a bob with all the buttons
  69.              pointer;           // a pointer bob
  70. BITMAP_IMAGE cpanel;            // the control panel
  71. BITMAP_IMAGE canvas;            // off screen drawing canvas
  72.  
  73. int mouse_x,                    // used to track mouse
  74.     mouse_y;
  75.     
  76. UCHAR mouse_color=100;          // color of mouse brush
  77.  
  78. int command_state=0;            // state of user command
  79.  
  80. // position of control buttons
  81. int buttons_x[] = {509, 559, 509, 559};
  82. int buttons_y[] = {344, 344, 383, 383};
  83.  
  84. // on/off state of buttons
  85. int buttons_state[] = {0,1,0,0};
  86.  
  87. // FUNCTIONS //////////////////////////////////////////////
  88.  
  89. LRESULT CALLBACK WindowProc(HWND hwnd, 
  90.                             UINT msg, 
  91.                             WPARAM wparam, 
  92.                             LPARAM lparam)
  93. {
  94. // this is the main message handler of the system
  95. PAINTSTRUCT    ps;           // used in WM_PAINT
  96. HDC            hdc;       // handle to a device context
  97.  
  98. // what is the message 
  99. switch(msg)
  100.     {    
  101.     case WM_CREATE: 
  102.         {
  103.         // do initialization stuff here
  104.         return(0);
  105.         } break;
  106.  
  107.     case WM_PAINT:
  108.          {
  109.          // start painting
  110.          hdc = BeginPaint(hwnd,&ps);
  111.  
  112.          // end painting
  113.          EndPaint(hwnd,&ps);
  114.          return(0);
  115.         } break;
  116.  
  117.     case WM_DESTROY: 
  118.         {
  119.         // kill the application            
  120.         PostQuitMessage(0);
  121.         return(0);
  122.         } break;
  123.  
  124.     default:break;
  125.  
  126.     } // end switch
  127.  
  128. // process any messages that we didn't take care of 
  129. return (DefWindowProc(hwnd, msg, wparam, lparam));
  130.  
  131. } // end WinProc
  132.  
  133. // WINMAIN ////////////////////////////////////////////////
  134.  
  135. int WINAPI WinMain(    HINSTANCE hinstance,
  136.                     HINSTANCE hprevinstance,
  137.                     LPSTR lpcmdline,
  138.                     int ncmdshow)
  139. {
  140. // this is the winmain function
  141.  
  142. WNDCLASS winclass;    // this will hold the class we create
  143. HWND     hwnd;        // generic window handle
  144. MSG         msg;        // generic message
  145. HDC      hdc;       // generic dc
  146. PAINTSTRUCT ps;     // generic paintstruct
  147.  
  148. // first fill in the window class stucture
  149. winclass.style            = CS_DBLCLKS | CS_OWNDC | 
  150.                           CS_HREDRAW | CS_VREDRAW;
  151. winclass.lpfnWndProc    = WindowProc;
  152. winclass.cbClsExtra        = 0;
  153. winclass.cbWndExtra        = 0;
  154. winclass.hInstance        = hinstance;
  155. winclass.hIcon            = LoadIcon(NULL, IDI_APPLICATION);
  156. winclass.hCursor        = LoadCursor(NULL, IDC_ARROW);
  157. winclass.hbrBackground    = (HBRUSH)GetStockObject(BLACK_BRUSH);
  158. winclass.lpszMenuName    = NULL; 
  159. winclass.lpszClassName    = WINDOW_CLASS_NAME;
  160.  
  161. // register the window class
  162. if (!RegisterClass(&winclass))
  163.     return(0);
  164.  
  165. // create the window, note the use of WS_POPUP
  166. if (!(hwnd = CreateWindow(WINDOW_CLASS_NAME, // class
  167.                           "WinX Game Console",     // title
  168.                           WS_POPUP | WS_VISIBLE,
  169.                            0,0,       // x,y
  170.                           WINDOW_WIDTH,  // width
  171.                           WINDOW_HEIGHT, // height
  172.                           NULL,       // handle to parent 
  173.                           NULL,       // handle to menu
  174.                           hinstance,// instance
  175.                           NULL)))    // creation parms
  176. return(0);
  177.  
  178. // save the window handle and instance in a global
  179. main_window_handle = hwnd;
  180. main_instance      = hinstance;
  181.  
  182. // perform all game console specific initialization
  183. Game_Init();
  184.  
  185. // enter main event loop
  186. while(1)
  187.     {
  188.     if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
  189.         { 
  190.         // test if this is a quit
  191.         if (msg.message == WM_QUIT)
  192.            break;
  193.     
  194.         // translate any accelerator keys
  195.         TranslateMessage(&msg);
  196.  
  197.         // send the message to the window proc
  198.         DispatchMessage(&msg);
  199.         } // end if
  200.     
  201.     // main game processing goes here
  202.     Game_Main();
  203.  
  204.     } // end while
  205.  
  206. // shutdown game and release all resources
  207. Game_Shutdown();
  208.  
  209. // return to Windows like this
  210. return(msg.wParam);
  211.  
  212. } // end WinMain
  213.  
  214. // WINX GAME PROGRAMMING CONSOLE FUNCTIONS ////////////////
  215.  
  216. int Game_Init(void *parms)
  217. {
  218. // this function is where you do all the initialization 
  219. // for your game
  220.  
  221. int index;    
  222.  
  223. // set up screen dimensions
  224. screen_width  = 640;
  225. screen_height = 480;
  226. screen_bpp    = 8;
  227.  
  228. // initialize directdraw
  229. DD_Init(screen_width, screen_height, screen_bpp);
  230.  
  231. // initialize directinput and the mouse ///////////////////////
  232.  
  233. // first create the direct input object
  234. DirectInput8Create(main_instance, DIRECTINPUT_VERSION, IID_IDirectInput8, (void **)&lpdi,NULL);
  235.  
  236. // create a mouse device  /////////////////////////////////////
  237. lpdi->CreateDevice(GUID_SysMouse, &lpdimouse, NULL);
  238.  
  239. // set cooperation level
  240. lpdimouse->SetCooperativeLevel(main_window_handle, DISCL_NONEXCLUSIVE | DISCL_BACKGROUND);
  241.  
  242. // set data format
  243. lpdimouse->SetDataFormat(&c_dfDIMouse);
  244.  
  245. // acquire the mouse
  246. lpdimouse->Acquire();
  247.  
  248. /////////////////////////////////////////////////////////////////
  249.  
  250. // set the global mouse position
  251. mouse_x = SCREEN_WIDTH/2;
  252. mouse_y = SCREEN_HEIGHT/2;
  253.  
  254. // load the master bitmap in with all the graphics
  255. Load_Bitmap_File(&bitmap8bit, "PAINT.BMP");
  256. Set_Palette(bitmap8bit.palette);
  257.  
  258. // make sure all the surfaces are clean before starting
  259. DD_Fill_Surface(lpddsback, 0);
  260. DD_Fill_Surface(lpddsprimary, 0);
  261.  
  262. // create the pointer bob
  263. Create_BOB(&pointer,mouse_x,mouse_y,32,34,1,
  264.            BOB_ATTR_VISIBLE | BOB_ATTR_SINGLE_FRAME,DDSCAPS_SYSTEMMEMORY);    
  265.  
  266. // load the image for the pointer in
  267. Load_Frame_BOB(&pointer,&bitmap8bit,0,0,2,BITMAP_EXTRACT_MODE_CELL);  
  268.  
  269. // create the button bob
  270. Create_BOB(&buttons,0,0,32,34,8,
  271.            BOB_ATTR_VISIBLE | BOB_ATTR_MULTI_FRAME,DDSCAPS_SYSTEMMEMORY);    
  272.  
  273. // load buttons in, two banks of 4, all the off's, then all the on's
  274. for (index=0; index<8; index++)
  275.      Load_Frame_BOB(&buttons,&bitmap8bit,index, index%4,index/4,BITMAP_EXTRACT_MODE_CELL);  
  276.  
  277. // create the bitmap to hold the control panel
  278. Create_Bitmap(&cpanel,500,0,104,424);
  279. Load_Image_Bitmap(&cpanel, &bitmap8bit,150,0,BITMAP_EXTRACT_MODE_ABS);
  280.  
  281. // create the drawing canvas bitmap
  282. Create_Bitmap(&canvas,0,0,500,SCREEN_HEIGHT);
  283. memset(canvas.buffer,0,canvas.width*canvas.height);
  284. canvas.attr = BITMAP_ATTR_LOADED;
  285.  
  286. // clear out the canvas
  287. // memset(canvas.buffer,0,canvas.width*canvas.height);
  288.  
  289. // set clipping rectangle to screen extents so mouse cursor
  290. // doens't mess up at edges
  291. RECT screen_rect = {0,0,screen_width,screen_height};
  292. lpddclipper = DD_Attach_Clipper(lpddsback,1,&screen_rect);
  293.  
  294. // hide the mouse
  295. ShowCursor(FALSE);
  296.  
  297. // return success
  298. return(1);
  299.  
  300. } // end Game_Init
  301.  
  302. ///////////////////////////////////////////////////////////
  303.  
  304. int Game_Shutdown(void *parms)
  305. {
  306. // this function is where you shutdown your game and
  307. // release all resources that you allocated
  308.  
  309. // first unacquire the mouse
  310. lpdimouse->Unacquire();
  311.  
  312. // now release the mouse
  313. lpdimouse->Release();
  314.  
  315. // release directinput
  316. lpdi->Release();
  317.  
  318. // unload the bitmap file
  319. Unload_Bitmap_File(&bitmap8bit);
  320.  
  321. // delete all bobs and bitmaps
  322. Destroy_BOB(&buttons);
  323. Destroy_BOB(&pointer);
  324. Destroy_Bitmap(&cpanel);
  325. Destroy_Bitmap(&canvas);
  326.  
  327. // shutdown directdraw
  328. DD_Shutdown();
  329.  
  330. // return success
  331. return(1);
  332. } // end Game_Shutdown
  333.  
  334. ///////////////////////////////////////////////////////////
  335.  
  336. int Game_Main(void *parms)
  337. {
  338. // this is the workhorse of your game it will be called
  339. // continuously in real-time this is like main() in C
  340. // all the calls for you game go here!
  341.  
  342. int index; // looping var
  343.  
  344. // check of user is trying to exit
  345. if (KEY_DOWN(VK_ESCAPE) || KEY_DOWN(VK_SPACE))
  346.     PostMessage(main_window_handle, WM_DESTROY,0,0);
  347.  
  348. // start the timing clock
  349. Start_Clock();
  350.  
  351. // clear the drawing surface
  352. DD_Fill_Surface(lpddsback, 0);
  353.  
  354. // get the input from the mouse
  355. lpdimouse->GetDeviceState(sizeof(DIMOUSESTATE), (LPVOID)&mouse_state);
  356.  
  357. // move the mouse cursor
  358. mouse_x+=(mouse_state.lX);
  359. mouse_y+=(mouse_state.lY);
  360.  
  361. // test bounds
  362.  
  363. // first x boundaries
  364. if (mouse_x >= screen_width)
  365.    mouse_x = screen_width-1;
  366. else
  367. if (mouse_x < 0)
  368.    mouse_x = 0;
  369.  
  370. // now the y boundaries
  371. if (mouse_y >= screen_height)
  372.    mouse_y= screen_height-1;
  373. else
  374. if (mouse_y < 0)
  375.    mouse_y = 0;
  376.  
  377. // position the pointer bob to the mouse coords
  378. pointer.x = mouse_x;
  379. pointer.y = mouse_y;
  380.  
  381. // test what the user is doing with the mouse
  382. if ((mouse_x > 3) && (mouse_x < 500-3) && 
  383.     (mouse_y > 3) && (mouse_y < SCREEN_HEIGHT-3))
  384.    {
  385.    // mouse is within canvas region
  386.  
  387.    // if left button is down then draw
  388.    if (mouse_state.rgbButtons[0])
  389.       {
  390.       // test drawing mode
  391.       if (buttons_state[BUTTON_PENCIL])
  392.          {
  393.          // draw a pixel 
  394.          Draw_Pixel(mouse_x, mouse_y, mouse_color, canvas.buffer, canvas.width);
  395.          Draw_Pixel(mouse_x+1, mouse_y, mouse_color, canvas.buffer, canvas.width);
  396.          Draw_Pixel(mouse_x, mouse_y+1, mouse_color, canvas.buffer, canvas.width);
  397.          Draw_Pixel(mouse_x+1, mouse_y+1, mouse_color, canvas.buffer, canvas.width);
  398.          }
  399.       else
  400.          {
  401.          // draw spray
  402.          for (index=0; index<10; index++)
  403.              {
  404.              // get next particle
  405.              int sx=mouse_x-8+rand()%16;
  406.              int sy=mouse_y-8+rand()%16;
  407.             
  408.              // make sure particle is in bounds
  409.              if (sx > 0 && sx < 500 && sy > 0 && sy < screen_height)
  410.                 Draw_Pixel(sx, sy, mouse_color, canvas.buffer, canvas.width);
  411.              } // end for index
  412.  
  413.          } // end else
  414.  
  415.       } // end if left button
  416.     else // right button is eraser
  417.     if (mouse_state.rgbButtons[1])
  418.        {
  419.        // test drawing mode
  420.        if (buttons_state[BUTTON_PENCIL]) 
  421.           {
  422.           // erase a pixel 
  423.           Draw_Pixel(mouse_x, mouse_y, 0, canvas.buffer, canvas.width);
  424.           Draw_Pixel(mouse_x+1, mouse_y, 0, canvas.buffer, canvas.width);
  425.           Draw_Pixel(mouse_x, mouse_y+1, 0, canvas.buffer, canvas.width);
  426.           Draw_Pixel(mouse_x+1, mouse_y+1, 0, canvas.buffer, canvas.width);
  427.           } // end if
  428.        else
  429.           {
  430.           // erase spray
  431.           for (index=0; index<20; index++)
  432.               {
  433.               // get next particle
  434.               int sx=mouse_x-8+rand()%16;
  435.               int sy=mouse_y-8+rand()%16;
  436.             
  437.               // make sure particle is in bounds
  438.               if (sx > 0 && sx < 500 && sy > 0 && sy < screen_height)
  439.                  Draw_Pixel(sx, sy, 0, canvas.buffer, canvas.width);
  440.               } // end for index
  441.           
  442.           } // end else
  443.        
  444.        } // end if left button
  445.   
  446.    } // end if
  447. else
  448. if ( (mouse_x > 500+16) && (mouse_x < 500+16+8*9) &&
  449.      (mouse_y > 8)      && (mouse_y < 8+32*9))
  450.    {
  451.    // within palette
  452.  
  453.    // test if button left button is down
  454.    if (mouse_state.rgbButtons[0])
  455.       {
  456.       // see what color cell user is pointing to
  457.       int cell_x = (mouse_x - (500+16))/9;
  458.       int cell_y = (mouse_y - (8))/9;
  459.  
  460.       // change color
  461.       mouse_color = cell_x + cell_y*8;
  462.  
  463.       } // end if
  464.    } // end if
  465. else
  466. if ((mouse_x > 500) && (mouse_x < (500+100)) &&
  467.     (mouse_y > 344) && (mouse_y < (383+34)) )
  468.    {  
  469.    // within button area
  470.    // test for each button
  471.    for (index=0; index<4; index++)
  472.        {
  473.        if ((mouse_x > buttons_x[index]) && (mouse_x < (buttons_x[index]+32)) &&
  474.            (mouse_y > buttons_y[index]) && (mouse_y < (buttons_y[index]+34)) )
  475.            break;
  476.  
  477.        } // end for
  478.  
  479.    // at this point we know where the user is, now determine what he
  480.    // is doing with the buttons
  481.    switch(index)
  482.          {
  483.          case BUTTON_SPRAY:
  484.              {
  485.              // if left button is down simply activate spray mode
  486.              if (mouse_state.rgbButtons[0])
  487.                 {
  488.                 // depress button
  489.                 buttons_state[index] = 1;
  490.  
  491.                // de-activate pencil mode
  492.                 buttons_state[BUTTON_PENCIL] = 0;
  493.                 } // end if
  494.              else
  495.                 {
  496.                 // make sure button is up
  497.                 // buttons_state[index] = 0;
  498.                 } // end else
  499.  
  500.              } break;
  501.          
  502.          case BUTTON_PENCIL:
  503.              {
  504.              // if left button is down activate spray mode
  505.              if (mouse_state.rgbButtons[0])
  506.                 {
  507.                 // depress button
  508.                 buttons_state[index] = 1;
  509.  
  510.                 // de-activate spray mode
  511.                 buttons_state[BUTTON_SPRAY] = 0;
  512.  
  513.                 } // end if
  514.              else
  515.                 {
  516.                 // make sure button is up
  517.                 // buttons_state[index] = 0;
  518.                 } // end else
  519.  
  520.              } break;
  521.  
  522.          case BUTTON_ERASE:
  523.              {
  524.              // test if left button is down, if so clear screen
  525.              if (mouse_state.rgbButtons[0])
  526.                 {
  527.                 // clear memory
  528.                 memset(canvas.buffer,0,canvas.width*canvas.height);
  529.  
  530.                 // depress button
  531.                 buttons_state[index] = 1;
  532.                 } // end if
  533.              else
  534.                 {
  535.                 // make sure button is up
  536.                 buttons_state[index] = 0;
  537.                 } // end else
  538.              } break;
  539.          
  540.          case BUTTON_EXIT:
  541.              {
  542.              // test if left button down, if so bail
  543.              if (mouse_state.rgbButtons[0])
  544.                   PostMessage(main_window_handle, WM_DESTROY,0,0);
  545.  
  546.              } break;
  547.  
  548.          } // end switch
  549.  
  550.    } // end if
  551. else
  552.    {
  553.    // no mans land
  554.  
  555.    } // end else
  556.  
  557. // lock back buffer
  558. DD_Lock_Back_Surface();
  559.  
  560. // draw the canvas
  561. Draw_Bitmap(&canvas, back_buffer, back_lpitch,0);
  562.  
  563. // draw control panel
  564. Draw_Bitmap(&cpanel,back_buffer,back_lpitch,0);
  565.  
  566. // unlock back buffer
  567. DD_Unlock_Back_Surface();
  568.  
  569. // draw the color palette
  570. for (int col=0; col < 256; col++)
  571.     {
  572.     Draw_Rectangle(500+16+(col%8)*9,   8+(col/8)*9,
  573.                    500+16+(col%8)*9+8, 8+(col/8)*9+8,
  574.                    col,lpddsback);
  575.     
  576.     } // end for col
  577.  
  578. // draw the current color selected
  579. Draw_Rectangle(533,306,533+34,306+34,mouse_color,lpddsback);
  580.  
  581. // draw the buttons
  582. for (index=0; index<4; index++)
  583.     {
  584.     // set position of button bob
  585.     buttons.x = buttons_x[index];
  586.     buttons.y = buttons_y[index];
  587.  
  588.     // now select the on/off frame based on if the
  589.     // button is off
  590.     if (buttons_state[index]==0)
  591.         buttons.curr_frame = index;
  592.     else // button is on
  593.         buttons.curr_frame = index+4;
  594.  
  595.     // draw the button
  596.     Draw_BOB(&buttons, lpddsback);
  597.  
  598.     } // end for index
  599.  
  600. // display coords
  601. sprintf(buffer,"(%d,%d)",mouse_x,mouse_y);
  602. Draw_Text_GDI(buffer, 520,450,RGB(0,255,0),lpddsback);
  603. Draw_Text_GDI("Painting For Dummies!",0,0,RGB(255,255,45),lpddsback);
  604.  
  605. // draw the cursor last
  606. Draw_BOB(&pointer,lpddsback);
  607.  
  608. // flip the surfaces
  609. DD_Flip();
  610.  
  611. // sync to 3o fps
  612. Wait_Clock(30);
  613.  
  614.  
  615. // return success
  616. return(1);
  617.  
  618. } // end Game_Main
  619.  
  620. //////////////////////////////////////////////////////////