home *** CD-ROM | disk | FTP | other *** search
/ Windows Game Programming for Dummies (2nd Edition) / WinGamProgFD.iso / mac / Source / GPCHAP10 / Prog10_7_16b.cpp < prev    next >
C/C++ Source or Header  |  2002-04-27  |  17KB  |  588 lines

  1. // PROG10_7_16b.CPP - a demo of bit blitting from secondary
  2. // surface to primary surface
  3. // 16-bit version
  4.  
  5. // INCLUDES ///////////////////////////////////////////////
  6. #define WIN32_LEAN_AND_MEAN  
  7. #define INITGUID
  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. // this builds a 16 bit color value in 5.5.5 format (1-bit alpha mode)
  46. #define _RGB16BIT555(r,g,b) ((b & 31) + ((g & 31) << 5) + ((r & 31) << 10))
  47.  
  48. // this builds a 16 bit color value in 5.6.5 format (green dominate mode)
  49. #define _RGB16BIT565(r,g,b) ((b & 31) + ((g & 63) << 5) + ((r & 31) << 11))
  50.  
  51. // TYPES //////////////////////////////////////////////////
  52.  
  53. typedef unsigned short USHORT;
  54. typedef unsigned short WORD;
  55. typedef unsigned char  UCHAR;
  56. typedef unsigned char  BYTE;
  57.  
  58. // container structure for bitmaps .BMP file
  59. typedef struct BITMAP_FILE_TAG
  60.         {
  61.         BITMAPFILEHEADER bitmapfileheader;  // this contains the bitmapfile header
  62.         BITMAPINFOHEADER bitmapinfoheader;  // this is all the info including the palette
  63.         PALETTEENTRY     palette[256];      // we will store the palette here
  64.         UCHAR            *buffer;           // this is a pointer to the data
  65.  
  66.         } BITMAP_FILE, *BITMAP_FILE_PTR;
  67.  
  68. // PROTOTYPES /////////////////////////////////////////////
  69.  
  70. int Game_Init(void *parms=NULL);
  71. int Game_Shutdown(void *parms=NULL);
  72. int Game_Main(void *parms=NULL);
  73.  
  74. int Load_Bitmap_File(BITMAP_FILE_PTR bitmap, char *filename);
  75. int Unload_Bitmap_File(BITMAP_FILE_PTR bitmap);
  76. int Flip_Bitmap(UCHAR *image, int bytes_per_line, int height);
  77.  
  78. // GLOBALS ////////////////////////////////////////////////
  79.  
  80. HWND main_window_handle = NULL; // save the window handle
  81. HINSTANCE main_instance = NULL; // save the instance
  82. char buffer[80];                // used to print text
  83.  
  84. LPDIRECTDRAW7        lpdd         = NULL;  // dd object
  85. LPDIRECTDRAWSURFACE7 lpddsprimary = NULL;  // dd primary surface
  86. LPDIRECTDRAWSURFACE7 lpddsback    = NULL;  // dd back surface
  87. LPDIRECTDRAWPALETTE  lpddpal      = NULL;  // a pointer to the created dd palette
  88. PALETTEENTRY         palette[256];         // color 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. USHORT               *primary_buffer = NULL; // primary video buffer
  93. USHORT               *back_buffer    = NULL; // secondary back buffer
  94. BITMAP_FILE          bitmap16bit,            // a 16 bit bitmap file
  95.                      bitmap8bit;             // a 8 bit bitmap file
  96.  
  97. // FUNCTIONS //////////////////////////////////////////////
  98.  
  99. LRESULT CALLBACK WindowProc(HWND hwnd, 
  100.                             UINT msg, 
  101.                             WPARAM wparam, 
  102.                             LPARAM lparam)
  103. {
  104. // this is the main message handler of the system
  105. PAINTSTRUCT    ps;           // used in WM_PAINT
  106. HDC            hdc;       // handle to a device context
  107.  
  108. // what is the message 
  109. switch(msg)
  110.     {    
  111.     case WM_CREATE: 
  112.         {
  113.         // do initialization stuff here
  114.         return(0);
  115.         } break;
  116.  
  117.     case WM_PAINT:
  118.          {
  119.          // start painting
  120.          hdc = BeginPaint(hwnd,&ps);
  121.  
  122.          // end painting
  123.          EndPaint(hwnd,&ps);
  124.          return(0);
  125.         } break;
  126.  
  127.     case WM_DESTROY: 
  128.         {
  129.         // kill the application            
  130.         PostQuitMessage(0);
  131.         return(0);
  132.         } break;
  133.  
  134.     default:break;
  135.  
  136.     } // end switch
  137.  
  138. // process any messages that we didn't take care of 
  139. return (DefWindowProc(hwnd, msg, wparam, lparam));
  140.  
  141. } // end WinProc
  142.  
  143. // WINMAIN ////////////////////////////////////////////////
  144.  
  145. int WINAPI WinMain(    HINSTANCE hinstance,
  146.                     HINSTANCE hprevinstance,
  147.                     LPSTR lpcmdline,
  148.                     int ncmdshow)
  149. {
  150.  
  151. WNDCLASS winclass;    // this will hold the class we create
  152. HWND     hwnd;        // generic window handle
  153. MSG         msg;        // generic message
  154. HDC      hdc;       // generic dc
  155. PAINTSTRUCT ps;     // generic paintstruct
  156.  
  157. // first fill in the window class stucture
  158. winclass.style            = CS_DBLCLKS | CS_OWNDC | 
  159.                           CS_HREDRAW | CS_VREDRAW;
  160. winclass.lpfnWndProc    = WindowProc;
  161. winclass.cbClsExtra        = 0;
  162. winclass.cbWndExtra        = 0;
  163. winclass.hInstance        = hinstance;
  164. winclass.hIcon            = LoadIcon(NULL, IDI_APPLICATION);
  165. winclass.hCursor        = LoadCursor(NULL, IDC_ARROW);
  166. winclass.hbrBackground    = (HBRUSH)GetStockObject(BLACK_BRUSH);
  167. winclass.lpszMenuName    = NULL; 
  168. winclass.lpszClassName    = WINDOW_CLASS_NAME;
  169.  
  170. // register the window class
  171. if (!RegisterClass(&winclass))
  172.     return(0);
  173.  
  174. // create the window, note the use of WS_POPUP
  175. if (!(hwnd = CreateWindow(WINDOW_CLASS_NAME, // class
  176.                           "WinX Game Console",     // title
  177.                           WS_POPUP | WS_VISIBLE,
  178.                            0,0,       // x,y
  179.                           WINDOW_WIDTH,  // width
  180.                           WINDOW_HEIGHT, // height
  181.                           NULL,       // handle to parent 
  182.                           NULL,       // handle to menu
  183.                           hinstance,// instance
  184.                           NULL)))    // creation parms
  185. return(0);
  186.  
  187. // hide the mouse
  188. ShowCursor(FALSE);
  189.  
  190. // save the window handle and instance in a global
  191. main_window_handle = hwnd;
  192. main_instance      = hinstance;
  193.  
  194. // perform all game console specific initialization
  195. Game_Init();
  196.  
  197. // enter main event loop
  198. while(1)
  199.     {
  200.     if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
  201.         { 
  202.         // test if this is a quit
  203.         if (msg.message == WM_QUIT)
  204.            break;
  205.     
  206.         // translate any accelerator keys
  207.         TranslateMessage(&msg);
  208.  
  209.         // send the message to the window proc
  210.         DispatchMessage(&msg);
  211.         } // end if
  212.     
  213.     // main game processing goes here
  214.     Game_Main();
  215.  
  216.     } // end while
  217.  
  218. // shutdown game and release all resources
  219. Game_Shutdown();
  220.  
  221. // return to Windows like this
  222. return(msg.wParam);
  223.  
  224. } // end WinMain
  225.  
  226. // WINX GAME PROGRAMMING CONSOLE FUNCTIONS ////////////////
  227.  
  228. int Game_Init(void *parms)
  229. {
  230. // this function is where you do all the initialization 
  231. // for your game
  232.  
  233. // create object and test for error
  234. if (DirectDrawCreateEx(NULL, (void **)&lpdd, IID_IDirectDraw7, NULL)!=DD_OK)
  235.    return(0);
  236.  
  237. // set cooperation level to windowed mode normal
  238. if (lpdd->SetCooperativeLevel(main_window_handle,
  239.            DDSCL_ALLOWMODEX | DDSCL_FULLSCREEN | 
  240.            DDSCL_EXCLUSIVE | DDSCL_ALLOWREBOOT)!=DD_OK)
  241.     return(0);
  242.  
  243. // set the display mode
  244. if (lpdd->SetDisplayMode(SCREEN_WIDTH,SCREEN_HEIGHT,SCREEN_BPP,0,0)!=DD_OK)
  245.    return(0);
  246.  
  247. // Create the primary surface
  248. memset(&ddsd,0,sizeof(ddsd));
  249. ddsd.dwSize = sizeof(ddsd);
  250. ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
  251.  
  252. // we need to let dd know that we want a complex 
  253. // flippable surface structure, set flags for that
  254. ddsd.ddsCaps.dwCaps = 
  255.   DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX;
  256.  
  257. // set the backbuffer count to 1
  258. ddsd.dwBackBufferCount = 1;
  259.  
  260. // create the primary surface
  261. lpdd->CreateSurface(&ddsd,&lpddsprimary,NULL);
  262.  
  263. // query for the backbuffer i.e the secondary surface
  264. ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
  265. lpddsprimary->GetAttachedSurface(&ddscaps,&lpddsback);
  266.  
  267. // now load the 16 bit color bitmap
  268. Load_Bitmap_File(&bitmap16bit, "ANDRE16.BMP");
  269.  
  270. // copy bitmap into secondary buffer
  271. // set up the surface description to lock the surface
  272. memset(&ddsd,0,sizeof(ddsd)); 
  273. ddsd.dwSize = sizeof(ddsd);
  274.  
  275. // lock the primary surface, note in a real game you would
  276. lpddsback->Lock(NULL,&ddsd, 
  277.                    DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT,NULL);
  278.  
  279. // get video pointer
  280. back_buffer = (USHORT *)ddsd.lpSurface;
  281.  
  282. // copy each bitmap line into primary buffer 
  283. // taking into consideration non-linear video 
  284. // cards and the memory pitch lPitch
  285. // also note that the bitmap buffer is ALWAYS a UCHAR * pointer
  286. // so we have to use the correct pointer arithematic based on 8 or 
  287. // 16/24 bit modes
  288. for (int y=0; y < SCREEN_HEIGHT; y++)
  289.     {
  290.     // copy the line
  291.     memcpy(&back_buffer[y*(ddsd.lPitch/2)],       // dest address
  292.            &bitmap16bit.buffer[y*SCREEN_WIDTH*2], // src address
  293.            SCREEN_WIDTH*2);                       // bytes to copy
  294.     } // end for y
  295.  
  296. // unlock the surface
  297. lpddsback->Unlock(NULL);
  298.  
  299. // return success
  300. return(1);
  301.  
  302. } // end Game_Init
  303.  
  304. ///////////////////////////////////////////////////////////
  305.  
  306. int Game_Shutdown(void *parms)
  307. {
  308. // this function is where you shutdown your game and
  309. // release all resources that you allocated
  310.  
  311. // first release the secondary surface
  312. if (lpddsback!=NULL)
  313.    lpddsback->Release();
  314.  
  315. // now release the primary surface
  316. if (lpddsprimary!=NULL)
  317.    lpddsprimary->Release();
  318.        
  319. // release the directdraw object
  320. if (lpdd!=NULL)
  321.    lpdd->Release();
  322.  
  323. // delete the bitmap 
  324. Unload_Bitmap_File(&bitmap16bit);
  325.  
  326. // return success
  327. return(1);
  328. } // end Game_Shutdown
  329.  
  330. ///////////////////////////////////////////////////////////
  331.  
  332. int Game_Main(void *parms)
  333. {
  334. // this is the workhorse of your game it will be called
  335. // continuously in real-time this is like main() in C
  336. // all the calls for you game go here!
  337.  
  338. // check of user is trying to exit
  339. if (KEY_DOWN(VK_ESCAPE) || KEY_DOWN(VK_SPACE))
  340.     PostMessage(main_window_handle, WM_DESTROY,0,0);
  341.  
  342. // select source position to grab bitmap from
  343. int source_x = rand()%SCREEN_WIDTH;
  344. int source_y = rand()%SCREEN_HEIGHT;
  345.  
  346. // select destination position to put to
  347. int dest_x = rand()%SCREEN_WIDTH;
  348. int dest_y = rand()%SCREEN_HEIGHT;
  349.  
  350. // select width and height of rectangle 
  351. int width = rand()%SCREEN_WIDTH;
  352. int height = rand()%SCREEN_HEIGHT;
  353.  
  354. // set up rectangles
  355. RECT source_rect, dest_rect;
  356.  
  357. source_rect.left   = source_x;
  358. source_rect.top    = source_y;
  359. source_rect.right  = source_x + width;
  360. source_rect.bottom = source_y + height;
  361.  
  362. dest_rect.left   = dest_x;
  363. dest_rect.top    = dest_y;
  364. dest_rect.right  = dest_x + width;
  365. dest_rect.bottom = dest_y + height;
  366.  
  367. // set up the color key so that color RGB 0,0,0 is transparent
  368. DDCOLORKEY col_key;
  369. col_key.dwColorSpaceLowValue  = _RGB16BIT565(0,0,0);
  370. col_key.dwColorSpaceHighValue = _RGB16BIT565(0,0,0);
  371.  
  372. // set the key
  373. lpddsback->SetColorKey(DDCKEY_SRCBLT, &col_key);
  374.  
  375. // perform the blit from back to primary
  376. lpddsprimary->Blt(&dest_rect, lpddsback, &source_rect, DDBLT_KEYSRC | DDBLT_WAIT, NULL);
  377.  
  378. // return success
  379. return(1);
  380.  
  381. } // end Game_Main
  382.  
  383. ///////////////////////////////////////////////////////////
  384.  
  385. int Load_Bitmap_File(BITMAP_FILE_PTR bitmap, char *filename)
  386. {
  387. // this function opens a bitmap file and loads the data into bitmap
  388.  
  389. int file_handle,  // the file handle
  390.     index;        // looping index
  391.  
  392. UCHAR *temp_buffer = NULL; // used to convert 24 bit images to 16 bit
  393. OFSTRUCT file_data;        // the file data information
  394.  
  395. // open the file if it exists
  396. if ((file_handle = OpenFile(filename,&file_data,OF_READ))==-1)
  397.    return(0);
  398.  
  399. // now load the bitmap file header
  400. _lread(file_handle, &bitmap->bitmapfileheader,sizeof(BITMAPFILEHEADER));
  401.  
  402. // test if this is a bitmap file
  403. if (bitmap->bitmapfileheader.bfType!=BITMAP_ID)
  404.    {
  405.    // close the file
  406.    _lclose(file_handle);
  407.  
  408.    // return error
  409.    return(0);
  410.    } // end if
  411.  
  412. // now we know this is a bitmap, so read in all the sections
  413.  
  414. // first the bitmap infoheader
  415.  
  416. // now load the bitmap file header
  417. _lread(file_handle, &bitmap->bitmapinfoheader,sizeof(BITMAPINFOHEADER));
  418.  
  419. // now load the color palette if there is one
  420. if (bitmap->bitmapinfoheader.biBitCount == 8)
  421.    {
  422.    _lread(file_handle, &bitmap->palette,256*sizeof(PALETTEENTRY));
  423.  
  424.    // now set all the flags in the palette correctly and fix the reversed 
  425.    // BGR RGBQUAD data format
  426.    for (index=0; index < 256; index++)
  427.        {
  428.        // reverse the red and green fields
  429.        int temp_color = bitmap->palette[index].peRed;
  430.        bitmap->palette[index].peRed  = bitmap->palette[index].peBlue;
  431.        bitmap->palette[index].peBlue = temp_color;
  432.        
  433.        // always set the flags word to this
  434.        bitmap->palette[index].peFlags = PC_NOCOLLAPSE;
  435.        } // end for index
  436.  
  437.     } // end if
  438.  
  439. // finally the image data itself
  440. _lseek(file_handle,-(int)(bitmap->bitmapinfoheader.biSizeImage),SEEK_END);
  441.  
  442. // now read in the image, if the image is 8 or 16 bit then simply read it
  443. // but if its 24 bit then read it into a temporary area and then convert
  444. // it to a 16 bit image
  445.  
  446. if (bitmap->bitmapinfoheader.biBitCount==8 || bitmap->bitmapinfoheader.biBitCount==16)
  447.    {
  448.    // allocate the memory for the image
  449.    if (!(bitmap->buffer = (UCHAR *)malloc(bitmap->bitmapinfoheader.biSizeImage)))
  450.       {
  451.       // close the file
  452.       _lclose(file_handle);
  453.  
  454.       // return error
  455.       return(0);
  456.       } // end if
  457.  
  458.    // now read it in
  459.    _lread(file_handle,bitmap->buffer,bitmap->bitmapinfoheader.biSizeImage);
  460.  
  461.    } // end if
  462. else
  463.    {
  464.    // this must be a 24 bit image, load it in and convert it to 16 bit
  465. //   printf("\nconverting 24 bit image...");
  466.  
  467.    // allocate temporary buffer
  468.    if (!(temp_buffer = (UCHAR *)malloc(bitmap->bitmapinfoheader.biSizeImage)))
  469.       {
  470.       // close the file
  471.       _lclose(file_handle);
  472.  
  473.       // return error
  474.       return(0);
  475.       } // end if
  476.    
  477.    // allocate final 16 bit storage buffer
  478.    if (!(bitmap->buffer=(UCHAR *)malloc(2*bitmap->bitmapinfoheader.biWidth*bitmap->bitmapinfoheader.biHeight)))
  479.       {
  480.       // close the file
  481.       _lclose(file_handle);
  482.  
  483.       // release working buffer
  484.       free(temp_buffer);
  485.  
  486.       // return error
  487.       return(0);
  488.       } // end if
  489.  
  490.    // now read it in
  491.    _lread(file_handle,temp_buffer,bitmap->bitmapinfoheader.biSizeImage);
  492.  
  493.    // now convert each 24 bit RGB value into a 16 bit value
  494.    for (index=0; index<bitmap->bitmapinfoheader.biWidth*bitmap->bitmapinfoheader.biHeight; index++)
  495.        {
  496.        // extract RGB components (note they are in memory BGR)
  497.        // also, assume 5.6.5 format, so scale appropriately
  498.        UCHAR red    = (temp_buffer[index*3 + 2] >> 3), // 5 bits
  499.              green  = (temp_buffer[index*3 + 1] >> 2), // 6 bits, change to 3 for 5 bits
  500.              blue   = (temp_buffer[index*3 + 0] >> 3); // 5 bits
  501.  
  502.        // build up 16 bit color word assume 5.6.5 format
  503.        USHORT color = _RGB16BIT565(red,green,blue);
  504.  
  505.        // write color to buffer
  506.        ((USHORT *)bitmap->buffer)[index] = color;
  507.  
  508.        } // end for index
  509.  
  510.    // finally write out the correct number of bits
  511.    bitmap->bitmapinfoheader.biBitCount=16;
  512.  
  513.    } // end if
  514.  
  515. #if 0
  516. // write the file info out 
  517. printf("\nfilename:%s \nsize=%d \nwidth=%d \nheight=%d \nbitsperpixel=%d \ncolors=%d \nimpcolors=%d",
  518.         filename,
  519.         bitmap->bitmapinfoheader.biSizeImage,
  520.         bitmap->bitmapinfoheader.biWidth,
  521.         bitmap->bitmapinfoheader.biHeight,
  522.         bitmap->bitmapinfoheader.biBitCount,
  523.         bitmap->bitmapinfoheader.biClrUsed,
  524.         bitmap->bitmapinfoheader.biClrImportant);
  525. #endif
  526.  
  527. // close the file
  528. _lclose(file_handle);
  529.  
  530. // flip the bitmap
  531. Flip_Bitmap(bitmap->buffer, 
  532.             bitmap->bitmapinfoheader.biWidth*(bitmap->bitmapinfoheader.biBitCount/8), 
  533.             bitmap->bitmapinfoheader.biHeight);
  534.  
  535. // return success
  536. return(1);
  537.  
  538. } // end Load_Bitmap_File
  539.  
  540. ///////////////////////////////////////////////////////////
  541.  
  542. int Unload_Bitmap_File(BITMAP_FILE_PTR bitmap)
  543. {
  544. // this function releases all memory associated with "bitmap"
  545. if (bitmap->buffer)
  546.    {
  547.    // release memory
  548.    free(bitmap->buffer);
  549.  
  550.    // reset pointer
  551.    bitmap->buffer = NULL;
  552.  
  553.    } // end if
  554.  
  555. // return success
  556. return(1);
  557.  
  558. } // end Unload_Bitmap_File
  559.  
  560. ///////////////////////////////////////////////////////////
  561.  
  562. int Flip_Bitmap(UCHAR *image, int bytes_per_line, int height)
  563. {
  564. // this function is used to flip upside down .BMP images
  565.  
  566. UCHAR *buffer; // used to perform the image processing
  567. int index;     // looping index
  568.  
  569. // allocate the temporary buffer
  570. if (!(buffer = (UCHAR *)malloc(bytes_per_line*height)))
  571.    return(0);
  572.  
  573. // copy image to work area
  574. memcpy(buffer,image,bytes_per_line*height);
  575.  
  576. // flip vertically
  577. for (index=0; index < height; index++)
  578.     memcpy(&image[((height-1) - index)*bytes_per_line],
  579.            &buffer[index*bytes_per_line], bytes_per_line);
  580.  
  581. // release the memory
  582. free(buffer);
  583.  
  584. // return success
  585. return(1);
  586.  
  587. } // end Flip_Bitmap
  588.