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

  1. // PROG11_5.CPP - a demo of creating a message box on a 
  2. // direct draw app
  3.  
  4. // INCLUDES ///////////////////////////////////////////////
  5. #define WIN32_LEAN_AND_MEAN  
  6. #define INITGUID
  7.  
  8.  
  9. #include <windows.h>   // include important windows stuff
  10. #include <windowsx.h> 
  11. #include <mmsystem.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.  
  26. // DEFINES ////////////////////////////////////////////////
  27.  
  28. // defines for windows 
  29. #define WINDOW_CLASS_NAME "WINXCLASS"  // class name
  30.  
  31. #define WINDOW_WIDTH  640         // size of window
  32. #define WINDOW_HEIGHT 480
  33. #define SCREEN_WIDTH  640         // size of screen
  34. #define SCREEN_HEIGHT 480
  35. #define SCREEN_BPP    16          // bits per pixel
  36.  
  37. #define BITMAP_ID     0x4D42      // universal id for a bitmap
  38.  
  39. // MACROS /////////////////////////////////////////////////
  40.  
  41. // these read the keyboard asynchronously
  42. #define KEY_DOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)
  43. #define KEY_UP(vk_code)   ((GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1)
  44.  
  45.  
  46. // this builds a 16 bit color value in 5.5.5 format (1-bit alpha mode)
  47. #define _RGB16BIT555(r,g,b) ((b & 31) + ((g & 31) << 5) + ((r & 31) << 10))
  48.  
  49. // this builds a 16 bit color value in 5.6.5 format (green dominate mode)
  50. #define _RGB16BIT565(r,g,b) ((b & 31) + ((g & 63) << 5) + ((r & 31) << 11))
  51.  
  52. // TYPES //////////////////////////////////////////////////
  53.  
  54. typedef unsigned short USHORT;
  55. typedef unsigned short WORD;
  56. typedef unsigned char  UCHAR;
  57. typedef unsigned char  BYTE;
  58.  
  59. // container structure for bitmaps .BMP file
  60. typedef struct BITMAP_FILE_TAG
  61.         {
  62.         BITMAPFILEHEADER bitmapfileheader;  // this contains the bitmapfile header
  63.         BITMAPINFOHEADER bitmapinfoheader;  // this is all the info including the palette
  64.         PALETTEENTRY     palette[256];      // we will store the palette here
  65.         UCHAR            *buffer;           // this is a pointer to the data
  66.  
  67.         } BITMAP_FILE, *BITMAP_FILE_PTR;
  68.  
  69. // PROTOTYPES /////////////////////////////////////////////
  70.  
  71. int Game_Init(void *parms=NULL);
  72. int Game_Shutdown(void *parms=NULL);
  73. int Game_Main(void *parms=NULL);
  74.  
  75. int Load_Bitmap_File(BITMAP_FILE_PTR bitmap, char *filename);
  76. int Unload_Bitmap_File(BITMAP_FILE_PTR bitmap);
  77. int Flip_Bitmap(UCHAR *image, int bytes_per_line, int height);
  78.  
  79. // GLOBALS ////////////////////////////////////////////////
  80.  
  81. HWND main_window_handle = NULL; // save the window handle
  82. HINSTANCE main_instance = NULL; // save the instance
  83. char buffer[80];                // used to print text
  84.  
  85. LPDIRECTDRAW7        lpdd         = NULL;  // dd object
  86. LPDIRECTDRAWSURFACE7 lpddsprimary = NULL;  // dd primary surface
  87. LPDIRECTDRAWSURFACE7 lpddsback    = NULL;  // dd back surface
  88. LPDIRECTDRAWPALETTE  lpddpal      = NULL;  // a pointer to the created dd palette
  89. DDSURFACEDESC2       ddsd;                 // a direct draw surface description struct
  90. DDSCAPS2             ddscaps;              // a direct draw surface capabilities struct
  91. HRESULT              ddrval;               // result back from dd calls
  92. UCHAR                *primary_buffer = NULL; // primary video buffer
  93. BITMAP_FILE          bitmap16bit;            // a 16 bit bitmap file
  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.  
  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. // hide the mouse
  186. ShowCursor(FALSE);
  187.  
  188. // save the window handle and instance in a global
  189. main_window_handle = hwnd;
  190. main_instance      = hinstance;
  191.  
  192. // perform all game console specific initialization
  193. Game_Init();
  194.  
  195. // enter main event loop
  196. while(1)
  197.     {
  198.     if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
  199.         { 
  200.         // test if this is a quit
  201.         if (msg.message == WM_QUIT)
  202.            break;
  203.     
  204.         // translate any accelerator keys
  205.         TranslateMessage(&msg);
  206.  
  207.         // send the message to the window proc
  208.         DispatchMessage(&msg);
  209.         } // end if
  210.     
  211.     // main game processing goes here
  212.     Game_Main();
  213.  
  214.     } // end while
  215.  
  216. // shutdown game and release all resources
  217. Game_Shutdown();
  218.  
  219. // return to Windows like this
  220. return(msg.wParam);
  221.  
  222. } // end WinMain
  223.  
  224. // WINX GAME PROGRAMMING CONSOLE FUNCTIONS ////////////////
  225.  
  226. int Game_Init(void *parms)
  227. {
  228. // this function is where you do all the initialization 
  229. // for your game
  230.  
  231. // create object and test for error
  232. if (DirectDrawCreateEx(NULL, (void **)&lpdd, IID_IDirectDraw7, NULL)!=DD_OK)
  233.    return(0);
  234.  
  235. // set cooperation level to windowed mode normal
  236. if (lpdd->SetCooperativeLevel(main_window_handle,
  237.            DDSCL_ALLOWMODEX | DDSCL_FULLSCREEN | 
  238.            DDSCL_EXCLUSIVE | DDSCL_ALLOWREBOOT)!=DD_OK)
  239.     return(0);
  240.  
  241. // set the display mode
  242. if (lpdd->SetDisplayMode(SCREEN_WIDTH,SCREEN_HEIGHT,SCREEN_BPP,0,0)!=DD_OK)
  243.    return(0);
  244.  
  245. // Create the primary surface
  246. memset(&ddsd,0,sizeof(ddsd));
  247. ddsd.dwSize         = sizeof(ddsd);
  248. ddsd.dwFlags        = DDSD_CAPS;
  249. ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
  250.  
  251. if (lpdd->CreateSurface(&ddsd,&lpddsprimary,NULL)!=DD_OK)
  252.    return(0);
  253.  
  254. // now load the 16 bit color bitmap
  255. Load_Bitmap_File(&bitmap16bit, "ANDRE16.BMP");
  256.  
  257. // return success
  258. return(1);
  259.  
  260. } // end Game_Init
  261.  
  262. ///////////////////////////////////////////////////////////
  263.  
  264. int Game_Shutdown(void *parms)
  265. {
  266. // this function is where you shutdown your game and
  267. // release all resources that you allocated
  268.  
  269. // first release the primary surface
  270. if (lpddsprimary!=NULL)
  271.    lpddsprimary->Release();
  272.        
  273. // release the directdraw object
  274. if (lpdd!=NULL)
  275.    lpdd->Release();
  276.  
  277. // delete the bitmap 
  278. Unload_Bitmap_File(&bitmap16bit);
  279.  
  280. // return success
  281. return(1);
  282. } // end Game_Shutdown
  283.  
  284. ///////////////////////////////////////////////////////////
  285.  
  286. int Game_Main(void *parms)
  287. {
  288. // this is the workhorse of your game it will be called
  289. // continuously in real-time this is like main() in C
  290. // all the calls for you game go here!
  291.  
  292. // check of user is trying to exit
  293. if (KEY_DOWN(VK_ESCAPE) || KEY_DOWN(VK_SPACE))
  294.     PostMessage(main_window_handle, WM_DESTROY,0,0);
  295.  
  296. // this will pop up a message box on top of the image
  297. if (KEY_DOWN('M'))
  298.    {
  299.    // show the mouse cursor
  300.    ShowCursor(TRUE);
  301.    
  302.    // display the GDI message box
  303.    MessageBox(main_window_handle,"What's Up Baby!","Message Box Test",MB_OK);
  304.    
  305.    // hide the mouse cursor
  306.    ShowCursor(FALSE);
  307.    } // end if
  308.  
  309. // set up the surface description to lock the surface
  310. memset(&ddsd,0,sizeof(ddsd)); 
  311. ddsd.dwSize = sizeof(ddsd);
  312.  
  313. // lock the primary surface, note in a real game you would
  314. lpddsprimary->Lock(NULL,&ddsd, 
  315.                    DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT,NULL);
  316.  
  317. // get video pointer
  318. primary_buffer = (UCHAR *)ddsd.lpSurface;
  319.  
  320. // copy each bitmap line into primary buffer 
  321. // taking into consideration non-linear video 
  322. // cards and the memory pitch lPitch
  323. for (int y=0; y < SCREEN_HEIGHT; y++)
  324.     {
  325.     // copy the line
  326.     memcpy(&primary_buffer[y*ddsd.lPitch], // dest address
  327.            &bitmap16bit.buffer[y*SCREEN_WIDTH*2],   // src address
  328.            SCREEN_WIDTH*2);                         // bytes to copy
  329.     } // end for y
  330.  
  331. // unlock the surface
  332. lpddsprimary->Unlock(NULL);
  333.  
  334. // return success
  335. return(1);
  336.  
  337. } // end Game_Main
  338.  
  339. ///////////////////////////////////////////////////////////
  340.  
  341. int Load_Bitmap_File(BITMAP_FILE_PTR bitmap, char *filename)
  342. {
  343. // this function opens a bitmap file and loads the data into bitmap
  344.  
  345. int file_handle,  // the file handle
  346.     index;        // looping index
  347.  
  348. UCHAR *temp_buffer = NULL; // used to convert 24 bit images to 16 bit
  349. OFSTRUCT file_data;        // the file data information
  350.  
  351. // open the file if it exists
  352. if ((file_handle = OpenFile(filename,&file_data,OF_READ))==-1)
  353.    return(0);
  354.  
  355. // now load the bitmap file header
  356. _lread(file_handle, &bitmap->bitmapfileheader,sizeof(BITMAPFILEHEADER));
  357.  
  358. // test if this is a bitmap file
  359. if (bitmap->bitmapfileheader.bfType!=BITMAP_ID)
  360.    {
  361.    // close the file
  362.    _lclose(file_handle);
  363.  
  364.    // return error
  365.    return(0);
  366.    } // end if
  367.  
  368. // now we know this is a bitmap, so read in all the sections
  369.  
  370. // first the bitmap infoheader
  371.  
  372. // now load the bitmap file header
  373. _lread(file_handle, &bitmap->bitmapinfoheader,sizeof(BITMAPINFOHEADER));
  374.  
  375. // now load the color palette if there is one
  376. if (bitmap->bitmapinfoheader.biBitCount == 8)
  377.    {
  378.    _lread(file_handle, &bitmap->palette,256*sizeof(PALETTEENTRY));
  379.  
  380.    // now set all the flags in the palette correctly and fix the reversed 
  381.    // BGR RGBQUAD data format
  382.    for (index=0; index < 256; index++)
  383.        {
  384.        // reverse the red and green fields
  385.        int temp_color = bitmap->palette[index].peRed;
  386.        bitmap->palette[index].peRed  = bitmap->palette[index].peBlue;
  387.        bitmap->palette[index].peBlue = temp_color;
  388.        
  389.        // always set the flags word to this
  390.        bitmap->palette[index].peFlags = PC_NOCOLLAPSE;
  391.        } // end for index
  392.  
  393.     } // end if
  394.  
  395. // finally the image data itself
  396. _lseek(file_handle,-(int)(bitmap->bitmapinfoheader.biSizeImage),SEEK_END);
  397.  
  398. // now read in the image, if the image is 8 or 16 bit then simply read it
  399. // but if its 24 bit then read it into a temporary area and then convert
  400. // it to a 16 bit image
  401.  
  402. if (bitmap->bitmapinfoheader.biBitCount==8 || bitmap->bitmapinfoheader.biBitCount==16)
  403.    {
  404.    // allocate the memory for the image
  405.    if (!(bitmap->buffer = (UCHAR *)malloc(bitmap->bitmapinfoheader.biSizeImage)))
  406.       {
  407.       // close the file
  408.       _lclose(file_handle);
  409.  
  410.       // return error
  411.       return(0);
  412.       } // end if
  413.  
  414.    // now read it in
  415.    _lread(file_handle,bitmap->buffer,bitmap->bitmapinfoheader.biSizeImage);
  416.  
  417.    } // end if
  418. else
  419.    {
  420.    // this must be a 24 bit image, load it in and convert it to 16 bit
  421. //   printf("\nconverting 24 bit image...");
  422.  
  423.    // allocate temporary buffer
  424.    if (!(temp_buffer = (UCHAR *)malloc(bitmap->bitmapinfoheader.biSizeImage)))
  425.       {
  426.       // close the file
  427.       _lclose(file_handle);
  428.  
  429.       // return error
  430.       return(0);
  431.       } // end if
  432.    
  433.    // allocate final 16 bit storage buffer
  434.    if (!(bitmap->buffer=(UCHAR *)malloc(2*bitmap->bitmapinfoheader.biWidth*bitmap->bitmapinfoheader.biHeight)))
  435.       {
  436.       // close the file
  437.       _lclose(file_handle);
  438.  
  439.       // release working buffer
  440.       free(temp_buffer);
  441.  
  442.       // return error
  443.       return(0);
  444.       } // end if
  445.  
  446.    // now read it in
  447.    _lread(file_handle,temp_buffer,bitmap->bitmapinfoheader.biSizeImage);
  448.  
  449.    // now convert each 24 bit RGB value into a 16 bit value
  450.    for (index=0; index<bitmap->bitmapinfoheader.biWidth*bitmap->bitmapinfoheader.biHeight; index++)
  451.        {
  452.        // extract RGB components (note they are in memory BGR)
  453.        // also, assume 5.6.5 format, so scale appropriately
  454.        UCHAR red    = (temp_buffer[index*3 + 2] >> 3), // 5 bits
  455.              green  = (temp_buffer[index*3 + 1] >> 2), // 6 bits, change to 3 for 5 bits
  456.              blue   = (temp_buffer[index*3 + 0] >> 3); // 5 bits
  457.  
  458.        // build up 16 bit color word assume 5.6.5 format
  459.        USHORT color = _RGB16BIT565(red,green,blue);
  460.  
  461.        // write color to buffer
  462.        ((USHORT *)bitmap->buffer)[index] = color;
  463.  
  464.        } // end for index
  465.  
  466.    // finally write out the correct number of bits
  467.    bitmap->bitmapinfoheader.biBitCount=16;
  468.  
  469.    } // end if
  470.  
  471. #if 0
  472. // write the file info out 
  473. printf("\nfilename:%s \nsize=%d \nwidth=%d \nheight=%d \nbitsperpixel=%d \ncolors=%d \nimpcolors=%d",
  474.         filename,
  475.         bitmap->bitmapinfoheader.biSizeImage,
  476.         bitmap->bitmapinfoheader.biWidth,
  477.         bitmap->bitmapinfoheader.biHeight,
  478.         bitmap->bitmapinfoheader.biBitCount,
  479.         bitmap->bitmapinfoheader.biClrUsed,
  480.         bitmap->bitmapinfoheader.biClrImportant);
  481. #endif
  482.  
  483. // close the file
  484. _lclose(file_handle);
  485.  
  486. // flip the bitmap
  487. Flip_Bitmap(bitmap->buffer, 
  488.             bitmap->bitmapinfoheader.biWidth*(bitmap->bitmapinfoheader.biBitCount/8), 
  489.             bitmap->bitmapinfoheader.biHeight);
  490.  
  491. // return success
  492. return(1);
  493.  
  494. } // end Load_Bitmap_File
  495.  
  496. ///////////////////////////////////////////////////////////
  497.  
  498. int Unload_Bitmap_File(BITMAP_FILE_PTR bitmap)
  499. {
  500. // this function releases all memory associated with "bitmap"
  501. if (bitmap->buffer)
  502.    {
  503.    // release memory
  504.    free(bitmap->buffer);
  505.  
  506.    // reset pointer
  507.    bitmap->buffer = NULL;
  508.  
  509.    } // end if
  510.  
  511. // return success
  512. return(1);
  513.  
  514. } // end Unload_Bitmap_File
  515.  
  516. ///////////////////////////////////////////////////////////
  517.  
  518.  
  519. int Flip_Bitmap(UCHAR *image, int bytes_per_line, int height)
  520. {
  521. // this function is used to flip upside down .BMP images
  522.  
  523. UCHAR *buffer; // used to perform the image processing
  524. int index;     // looping index
  525.  
  526. // allocate the temporary buffer
  527. if (!(buffer = (UCHAR *)malloc(bytes_per_line*height)))
  528.    return(0);
  529.  
  530. // copy image to work area
  531. memcpy(buffer,image,bytes_per_line*height);
  532.  
  533. // flip vertically
  534. for (index=0; index < height; index++)
  535.     memcpy(&image[((height-1) - index)*bytes_per_line],
  536.            &buffer[index*bytes_per_line], bytes_per_line);
  537.  
  538. // release the memory
  539. free(buffer);
  540.  
  541. // return success
  542. return(1);
  543.  
  544. } // end Flip_Bitmap
  545.