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

  1. // PROG11_1.CPP - a demo of blitter objects (BOBS) 
  2. // creates an asteroid field
  3.  
  4. // INCLUDES ///////////////////////////////////////////////
  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 <stdlib.h>
  14. #include <malloc.h>
  15. #include <memory.h>
  16. #include <string.h>
  17. #include <stdarg.h>
  18. #include <stdio.h>
  19. #include <math.h>
  20. #include <io.h>
  21. #include <fcntl.h>
  22.  
  23. #include <ddraw.h>  // directX includes
  24.  
  25. // DEFINES ////////////////////////////////////////////////
  26.  
  27. // defines for windows 
  28. #define WINDOW_CLASS_NAME "WINXCLASS"  // class name
  29.  
  30. #define WINDOW_WIDTH  800         // size of window
  31. #define WINDOW_HEIGHT 600
  32. #define SCREEN_WIDTH  800         // size of screen
  33. #define SCREEN_HEIGHT 600
  34. #define SCREEN_BPP    8           // bits per pixel
  35.  
  36. #define BITMAP_ID     0x4D42      // universal id for a bitmap
  37.  
  38. // defines for BOBs
  39. #define BOB_STATE_DEAD     0      // this is a dead bob
  40. #define BOB_STATE_ALIVE    1      // this is a live bob
  41. #define BOB_STATE_LOADED   2      // the bob has been loaded
  42.  
  43. // defines for asteroids
  44. #define NUM_ASTEROIDS      64     // number of active asteroids
  45.  
  46. // MACROS /////////////////////////////////////////////////
  47.  
  48. // these read the keyboard asynchronously
  49. #define KEY_DOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)
  50. #define KEY_UP(vk_code)   ((GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1)
  51.  
  52. // this builds a 16 bit color value in 5.5.5 format (1-bit alpha mode)
  53. #define _RGB16BIT555(r,g,b) ((b & 31) + ((g & 31) << 5) + ((r & 31) << 10))
  54.  
  55. // this builds a 16 bit color value in 5.6.5 format (green dominate mode)
  56. #define _RGB16BIT565(r,g,b) ((b & 31) + ((g & 63) << 5) + ((r & 31) << 11))
  57.  
  58. // TYPES //////////////////////////////////////////////////
  59.  
  60. typedef unsigned short USHORT;
  61. typedef unsigned short WORD;
  62. typedef unsigned char  UCHAR;
  63. typedef unsigned char  BYTE;
  64.  
  65. // container structure for bitmaps .BMP file
  66. typedef struct BITMAP_FILE_TAG
  67.         {
  68.         BITMAPFILEHEADER bitmapfileheader;  // this contains the bitmapfile header
  69.         BITMAPINFOHEADER bitmapinfoheader;  // this is all the info including the palette
  70.         PALETTEENTRY     palette[256];      // we will store the palette here
  71.         UCHAR            *buffer;           // this is a pointer to the data
  72.  
  73.         } BITMAP_FILE, *BITMAP_FILE_PTR;
  74.  
  75. // the blitter object structure BOB
  76. typedef struct BITMAP_OBJ_TYP
  77.         {
  78.         int state; // the state of the object (general)
  79.         int attr;  // attributes pertaining to the object (general)
  80.         int x,y;   // position bitmap will be displayed at
  81.         int xv,yv; // velocity of object
  82.         int width, height; // the width and height of the bitmap
  83.         LPDIRECTDRAWSURFACE7 image; // the bitmap surface itself
  84.  
  85.         } BITMAP_OBJ, *BITMAP_OBJ_PTR;
  86.  
  87. // PROTOTYPES /////////////////////////////////////////////
  88.  
  89. // game console
  90. int Game_Init(void *parms=NULL);
  91. int Game_Shutdown(void *parms=NULL);
  92. int Game_Main(void *parms=NULL);
  93.  
  94. // bitmaps
  95. int Load_Bitmap_File(BITMAP_FILE_PTR bitmap, char *filename);
  96. int Unload_Bitmap_File(BITMAP_FILE_PTR bitmap);
  97. int Flip_Bitmap(UCHAR *image, int bytes_per_line, int height);
  98.  
  99. // bobs
  100. int Draw_BOB(BITMAP_OBJ_PTR bob,LPDIRECTDRAWSURFACE7 dest);
  101. int Destroy_BOB(BITMAP_OBJ_PTR bob);
  102. int Create_BOB(BITMAP_OBJ_PTR bob,int width, int height,int attr, int flags);
  103. int Load_BOB(BITMAP_OBJ_PTR bob,BITMAP_FILE_PTR bitmap,int cx,int cy,int mode); 
  104.  
  105. // GLOBALS ////////////////////////////////////////////////
  106.  
  107. HWND main_window_handle = NULL; // save the window handle
  108. HINSTANCE main_instance = NULL; // save the instance
  109. char buffer[80];                // used to print text
  110.  
  111. LPDIRECTDRAW7        lpdd         = NULL;  // dd object
  112. LPDIRECTDRAWSURFACE7 lpddsprimary = NULL;  // dd primary surface
  113. LPDIRECTDRAWSURFACE7 lpddsback    = NULL;  // dd back surface
  114. LPDIRECTDRAWPALETTE  lpddpal      = NULL;  // a pointer to the created dd palette
  115. PALETTEENTRY         palette[256];         // color palette
  116. DDSURFACEDESC2       ddsd;                 // a direct draw surface description struct
  117. DDBLTFX              ddbltfx;              // used to fill
  118. DDSCAPS2             ddscaps;              // a direct draw surface capabilities struct
  119. HRESULT              ddrval;               // result back from dd calls
  120. UCHAR                *primary_buffer = NULL; // primary video buffer
  121. UCHAR                *back_buffer    = NULL; // secondary back buffer
  122. BITMAP_FILE          bitmap16bit,            // a 16 bit bitmap file
  123.                      bitmap8bit;             // a 8 bit bitmap file
  124.  
  125. BITMAP_OBJ           asteroids[NUM_ASTEROIDS]; // asteroid field
  126.  
  127. // FUNCTIONS //////////////////////////////////////////////
  128.  
  129. int Load_Bitmap_File(BITMAP_FILE_PTR bitmap, char *filename)
  130. {
  131. // this function opens a bitmap file and loads the data into bitmap
  132.  
  133. int file_handle,  // the file handle
  134.     index;        // looping index
  135.  
  136. UCHAR *temp_buffer = NULL; // used to convert 24 bit images to 16 bit
  137. OFSTRUCT file_data;        // the file data information
  138.  
  139. // open the file if it exists
  140. if ((file_handle = OpenFile(filename,&file_data,OF_READ))==-1)
  141.    return(0);
  142.  
  143. // now load the bitmap file header
  144. _lread(file_handle, &bitmap->bitmapfileheader,sizeof(BITMAPFILEHEADER));
  145.  
  146. // test if this is a bitmap file
  147. if (bitmap->bitmapfileheader.bfType!=BITMAP_ID)
  148.    {
  149.    // close the file
  150.    _lclose(file_handle);
  151.  
  152.    // return error
  153.    return(0);
  154.    } // end if
  155.  
  156. // now we know this is a bitmap, so read in all the sections
  157.  
  158. // first the bitmap infoheader
  159.  
  160. // now load the bitmap file header
  161. _lread(file_handle, &bitmap->bitmapinfoheader,sizeof(BITMAPINFOHEADER));
  162.  
  163. // now load the color palette if there is one
  164. if (bitmap->bitmapinfoheader.biBitCount == 8)
  165.    {
  166.    _lread(file_handle, &bitmap->palette,256*sizeof(PALETTEENTRY));
  167.  
  168.    // now set all the flags in the palette correctly and fix the reversed 
  169.    // BGR RGBQUAD data format
  170.    for (index=0; index < 256; index++)
  171.        {
  172.        // reverse the red and green fields
  173.        int temp_color = bitmap->palette[index].peRed;
  174.        bitmap->palette[index].peRed  = bitmap->palette[index].peBlue;
  175.        bitmap->palette[index].peBlue = temp_color;
  176.        
  177.        // always set the flags word to this
  178.        bitmap->palette[index].peFlags = PC_NOCOLLAPSE;
  179.        } // end for index
  180.  
  181.     } // end if
  182.  
  183. // finally the image data itself
  184. _lseek(file_handle,-(int)(bitmap->bitmapinfoheader.biSizeImage),SEEK_END);
  185.  
  186. // now read in the image, if the image is 8 or 16 bit then simply read it
  187. // but if its 24 bit then read it into a temporary area and then convert
  188. // it to a 16 bit image
  189.  
  190. if (bitmap->bitmapinfoheader.biBitCount==8 || bitmap->bitmapinfoheader.biBitCount==16)
  191.    {
  192.    // allocate the memory for the image
  193.    if (!(bitmap->buffer = (UCHAR *)malloc(bitmap->bitmapinfoheader.biSizeImage)))
  194.       {
  195.       // close the file
  196.       _lclose(file_handle);
  197.  
  198.       // return error
  199.       return(0);
  200.       } // end if
  201.  
  202.    // now read it in
  203.    _lread(file_handle,bitmap->buffer,bitmap->bitmapinfoheader.biSizeImage);
  204.  
  205.    } // end if
  206. else
  207.    {
  208.    // this must be a 24 bit image, load it in and convert it to 16 bit
  209. //   printf("\nconverting 24 bit image...");
  210.  
  211.    // allocate temporary buffer
  212.    if (!(temp_buffer = (UCHAR *)malloc(bitmap->bitmapinfoheader.biSizeImage)))
  213.       {
  214.       // close the file
  215.       _lclose(file_handle);
  216.  
  217.       // return error
  218.       return(0);
  219.       } // end if
  220.    
  221.    // allocate final 16 bit storage buffer
  222.    if (!(bitmap->buffer=(UCHAR *)malloc(2*bitmap->bitmapinfoheader.biWidth*bitmap->bitmapinfoheader.biHeight)))
  223.       {
  224.       // close the file
  225.       _lclose(file_handle);
  226.  
  227.       // release working buffer
  228.       free(temp_buffer);
  229.  
  230.       // return error
  231.       return(0);
  232.       } // end if
  233.  
  234.    // now read it in
  235.    _lread(file_handle,temp_buffer,bitmap->bitmapinfoheader.biSizeImage);
  236.  
  237.    // now convert each 24 bit RGB value into a 16 bit value
  238.    for (index=0; index<bitmap->bitmapinfoheader.biWidth*bitmap->bitmapinfoheader.biHeight; index++)
  239.        {
  240.        // extract RGB components (note they are in memory BGR)
  241.        // also, assume 5.6.5 format, so scale appropriately
  242.        UCHAR red    = (temp_buffer[index*3 + 2] >> 3), // 5 bits
  243.              green  = (temp_buffer[index*3 + 1] >> 2), // 6 bits, change to 3 for 5 bits
  244.              blue   = (temp_buffer[index*3 + 0] >> 3); // 5 bits
  245.  
  246.        // build up 16 bit color word assume 5.6.5 format
  247.        USHORT color = _RGB16BIT565(red,green,blue);
  248.  
  249.        // write color to buffer
  250.        ((USHORT *)bitmap->buffer)[index] = color;
  251.  
  252.        } // end for index
  253.  
  254.    // finally write out the correct number of bits
  255.    bitmap->bitmapinfoheader.biBitCount=16;
  256.  
  257.    } // end if
  258.  
  259. #if 0
  260. // write the file info out 
  261. printf("\nfilename:%s \nsize=%d \nwidth=%d \nheight=%d \nbitsperpixel=%d \ncolors=%d \nimpcolors=%d",
  262.         filename,
  263.         bitmap->bitmapinfoheader.biSizeImage,
  264.         bitmap->bitmapinfoheader.biWidth,
  265.         bitmap->bitmapinfoheader.biHeight,
  266.         bitmap->bitmapinfoheader.biBitCount,
  267.         bitmap->bitmapinfoheader.biClrUsed,
  268.         bitmap->bitmapinfoheader.biClrImportant);
  269. #endif
  270.  
  271. // close the file
  272. _lclose(file_handle);
  273.  
  274. // flip the bitmap
  275. Flip_Bitmap(bitmap->buffer, 
  276.             bitmap->bitmapinfoheader.biWidth*(bitmap->bitmapinfoheader.biBitCount/8), 
  277.             bitmap->bitmapinfoheader.biHeight);
  278.  
  279. // return success
  280. return(1);
  281.  
  282. } // end Load_Bitmap_File
  283.  
  284. ///////////////////////////////////////////////////////////
  285.  
  286. int Unload_Bitmap_File(BITMAP_FILE_PTR bitmap)
  287. {
  288. // this function releases all memory associated with "bitmap"
  289. if (bitmap->buffer)
  290.    {
  291.    // release memory
  292.    free(bitmap->buffer);
  293.  
  294.    // reset pointer
  295.    bitmap->buffer = NULL;
  296.  
  297.    } // end if
  298.  
  299. // return success
  300. return(1);
  301.  
  302. } // end Unload_Bitmap_File
  303.  
  304. ///////////////////////////////////////////////////////////
  305.  
  306. int Flip_Bitmap(UCHAR *image, int bytes_per_line, int height)
  307. {
  308. // this function is used to flip upside down .BMP images
  309.  
  310. UCHAR *buffer; // used to perform the image processing
  311. int index;     // looping index
  312.  
  313. // allocate the temporary buffer
  314. if (!(buffer = (UCHAR *)malloc(bytes_per_line*height)))
  315.    return(0);
  316.  
  317. // copy image to work area
  318. memcpy(buffer,image,bytes_per_line*height);
  319.  
  320. // flip vertically
  321. for (index=0; index < height; index++)
  322.     memcpy(&image[((height-1) - index)*bytes_per_line],
  323.            &buffer[index*bytes_per_line], bytes_per_line);
  324.  
  325. // release the memory
  326. free(buffer);
  327.  
  328. // return success
  329. return(1);
  330.  
  331. } // end Flip_Bitmap
  332.  
  333. ///////////////////////////////////////////////////////////
  334.  
  335. int Create_BOB(BITMAP_OBJ_PTR bob,    // the bob to create
  336.                int width, int height, // size of bob
  337.                int attr,              // attrs
  338.                int flags = 0)         // memory flag
  339. {
  340. // Create the BOB object, note that all BOBs 
  341. // are created as offscreen surfaces in VRAM as the
  342. // default, if you want to use system memory then
  343. // set flags equal to DDSCAPS_SYSTEMMEMORY
  344.  
  345. DDSURFACEDESC2 ddsd; // used to create surface
  346.  
  347. // set state and attributes of BOB
  348. bob->state = BOB_STATE_ALIVE;
  349. bob->attr  = attr;
  350. bob->image = NULL;
  351.  
  352. // set position and velocity to 0
  353. bob->x = bob->y = bob->xv = bob->yv = 0;
  354.  
  355. // set to access caps, width, and height
  356. memset(&ddsd,0,sizeof(ddsd));
  357. ddsd.dwSize  = sizeof(ddsd);
  358. ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
  359.  
  360. // set dimensions of the new bitmap surface
  361. ddsd.dwWidth  = bob->width = width;
  362. ddsd.dwHeight = bob->height = height;
  363.  
  364. // set surface to offscreen plain
  365. ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | flags;
  366.  
  367. // create the surface
  368. if (lpdd->CreateSurface(&ddsd,&(bob->image),NULL)!=DD_OK)
  369.    return(0);
  370.  
  371. // set color key to color 0
  372. DDCOLORKEY color_key; // used to set color key
  373. color_key.dwColorSpaceLowValue  = 0;
  374. color_key.dwColorSpaceHighValue = 0;
  375.  
  376. // now set the color key for source blitting
  377. (bob->image)->SetColorKey(DDCKEY_SRCBLT, &color_key);
  378.  
  379. // return success
  380. return(1);
  381.  
  382. } // end Create_BOB
  383.  
  384. ///////////////////////////////////////////////////////////
  385.  
  386. int Destroy_BOB(BITMAP_OBJ_PTR bob)
  387. {
  388. // destroy the BOB, simply release the surface
  389.  
  390. if (bob->image)
  391.    (bob->image)->Release();
  392. else
  393.    return(0);
  394.  
  395. // return success
  396. return(1);
  397.  
  398. } // end Destroy_BOB
  399.  
  400. ///////////////////////////////////////////////////////////
  401.  
  402. int Draw_BOB(BITMAP_OBJ_PTR bob,       // bob to draw
  403.              LPDIRECTDRAWSURFACE7 dest) // surface to draw the bob on
  404. {
  405. // draw a bob at the x,y defined in the BOB
  406. // on the destination surface defined in dest
  407.  
  408. RECT dest_rect,   // the destination rectangle
  409.      source_rect; // the source rectangle                             
  410.  
  411. // fill in the destination rect
  412. dest_rect.left   = bob->x;
  413. dest_rect.top    = bob->y;
  414. dest_rect.right  = bob->x+bob->width;
  415. dest_rect.bottom = bob->y+bob->height;
  416.  
  417. // fill in the source rect
  418. source_rect.left    = 0;
  419. source_rect.top     = 0;
  420. source_rect.right   = bob->width;
  421. source_rect.bottom  = bob->height;
  422.  
  423. // blt to destination surface
  424. dest->Blt(&dest_rect, bob->image,
  425.           &source_rect,(DDBLT_WAIT | DDBLT_KEYSRC),
  426.           NULL);
  427.  
  428. // return success
  429. return(1);
  430. } // end Draw_BOB
  431.  
  432. ///////////////////////////////////////////////////////////
  433.  
  434. int Load_BOB(BITMAP_OBJ_PTR bob, // bob to load with data
  435.              BITMAP_FILE_PTR bitmap, // bitmap to scan image data from
  436.              int cx,int cy,   // cell or absolute pos. to scan image from
  437.              int mode)    // if 0 then cx,cy is cell position, else 
  438.                           // cx,cy are absolute coords
  439. {
  440. // this function extracts a bitmap out of a bitmap file
  441.  
  442. UCHAR *source_ptr,   // working pointers
  443.       *dest_ptr;
  444.  
  445. DDSURFACEDESC2 ddsd;  //  direct draw surface description 
  446.  
  447. // test the mode of extraction, cell based or absolute
  448. if (mode==0)
  449.    {
  450.    // re-compute x,y
  451.    cx = cx*(bob->width+1) + 1;
  452.    cy = cy*(bob->height+1) + 1;
  453.    } // end if
  454.  
  455. // extract bitmap data
  456. source_ptr = bitmap->buffer +
  457.       cy*bitmap->bitmapinfoheader.biWidth+cx;
  458.  
  459. // get the addr to destination surface memory
  460.  
  461. // set size of the structure
  462. ddsd.dwSize = sizeof(ddsd);
  463.  
  464. // lock the display surface
  465. (bob->image)->Lock(NULL,
  466.                    &ddsd,
  467.                    DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR,
  468.                    NULL);
  469.  
  470. // assign a pointer to the memory surface for manipulation
  471. dest_ptr = (UCHAR *)ddsd.lpSurface;
  472.  
  473. // iterate thru each scanline and copy bitmap
  474. for (int index_y=0; index_y<bob->height; index_y++)
  475.     {
  476.     // copy next line of data to destination
  477.     memcpy(dest_ptr, source_ptr,bob->width);
  478.  
  479.     // advance pointers
  480.     dest_ptr   += (ddsd.lPitch);
  481.     source_ptr += bitmap->bitmapinfoheader.biWidth;
  482.     } // end for index_y
  483.  
  484. // unlock the surface 
  485. (bob->image)->Unlock(NULL);
  486.  
  487. // set state to loaded
  488. bob->state |= BOB_STATE_LOADED;
  489.  
  490. // return success
  491. return(1);
  492.  
  493. } // end Load_BOB
  494.  
  495. ///////////////////////////////////////////////////////////
  496.  
  497. LRESULT CALLBACK WindowProc(HWND hwnd, 
  498.                             UINT msg, 
  499.                             WPARAM wparam, 
  500.                             LPARAM lparam)
  501. {
  502. // this is the main message handler of the system
  503. PAINTSTRUCT    ps;           // used in WM_PAINT
  504. HDC            hdc;       // handle to a device context
  505.  
  506. // what is the message 
  507. switch(msg)
  508.     {    
  509.     case WM_CREATE: 
  510.         {
  511.         // do initialization stuff here
  512.         return(0);
  513.         } break;
  514.  
  515.     case WM_PAINT:
  516.          {
  517.          // start painting
  518.          hdc = BeginPaint(hwnd,&ps);
  519.  
  520.          // end painting
  521.          EndPaint(hwnd,&ps);
  522.          return(0);
  523.         } break;
  524.  
  525.     case WM_DESTROY: 
  526.         {
  527.         // kill the application            
  528.         PostQuitMessage(0);
  529.         return(0);
  530.         } break;
  531.  
  532.     default:break;
  533.  
  534.     } // end switch
  535.  
  536. // process any messages that we didn't take care of 
  537. return (DefWindowProc(hwnd, msg, wparam, lparam));
  538.  
  539. } // end WinProc
  540.  
  541. // WINMAIN ////////////////////////////////////////////////
  542.  
  543. int WINAPI WinMain(    HINSTANCE hinstance,
  544.                     HINSTANCE hprevinstance,
  545.                     LPSTR lpcmdline,
  546.                     int ncmdshow)
  547. {
  548.  
  549. WNDCLASS winclass;    // this will hold the class we create
  550. HWND     hwnd;        // generic window handle
  551. MSG         msg;        // generic message
  552. HDC      hdc;       // generic dc
  553. PAINTSTRUCT ps;     // generic paintstruct
  554.  
  555. // first fill in the window class stucture
  556. winclass.style            = CS_DBLCLKS | CS_OWNDC | 
  557.                           CS_HREDRAW | CS_VREDRAW;
  558. winclass.lpfnWndProc    = WindowProc;
  559. winclass.cbClsExtra        = 0;
  560. winclass.cbWndExtra        = 0;
  561. winclass.hInstance        = hinstance;
  562. winclass.hIcon            = LoadIcon(NULL, IDI_APPLICATION);
  563. winclass.hCursor        = LoadCursor(NULL, IDC_ARROW);
  564. winclass.hbrBackground    = (HBRUSH)GetStockObject(BLACK_BRUSH);
  565. winclass.lpszMenuName    = NULL; 
  566. winclass.lpszClassName    = WINDOW_CLASS_NAME;
  567.  
  568. // register the window class
  569. if (!RegisterClass(&winclass))
  570.     return(0);
  571.  
  572. // create the window, note the use of WS_POPUP
  573. if (!(hwnd = CreateWindow(WINDOW_CLASS_NAME, // class
  574.                           "WinX Game Console",     // title
  575.                           WS_POPUP | WS_VISIBLE,
  576.                            0,0,       // x,y
  577.                           WINDOW_WIDTH,  // width
  578.                           WINDOW_HEIGHT, // height
  579.                           NULL,       // handle to parent 
  580.                           NULL,       // handle to menu
  581.                           hinstance,// instance
  582.                           NULL)))    // creation parms
  583. return(0);
  584.  
  585. // hide the mouse
  586. ShowCursor(FALSE);
  587.  
  588. // save the window handle and instance in a global
  589. main_window_handle = hwnd;
  590. main_instance      = hinstance;
  591.  
  592. // perform all game console specific initialization
  593. Game_Init();
  594.  
  595. // enter main event loop
  596. while(1)
  597.     {
  598.     if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
  599.         { 
  600.         // test if this is a quit
  601.         if (msg.message == WM_QUIT)
  602.            break;
  603.     
  604.         // translate any accelerator keys
  605.         TranslateMessage(&msg);
  606.  
  607.         // send the message to the window proc
  608.         DispatchMessage(&msg);
  609.         } // end if
  610.     
  611.     // main game processing goes here
  612.     Game_Main();
  613.  
  614.     } // end while
  615.  
  616. // shutdown game and release all resources
  617. Game_Shutdown();
  618.  
  619. // return to Windows like this
  620. return(msg.wParam);
  621.  
  622. } // end WinMain
  623.  
  624. // WINX GAME PROGRAMMING CONSOLE FUNCTIONS ////////////////
  625.  
  626. int Game_Init(void *parms)
  627. {
  628. // this function is where you do all the initialization 
  629. // for your game
  630.  
  631. int index; // looping var
  632.  
  633. // create object and test for error
  634. if (DirectDrawCreateEx(NULL, (void **)&lpdd, IID_IDirectDraw7, NULL)!=DD_OK)
  635.    return(0);
  636.  
  637. // set cooperation level to windowed mode normal
  638. if (lpdd->SetCooperativeLevel(main_window_handle,
  639.            DDSCL_ALLOWMODEX | DDSCL_FULLSCREEN | 
  640.            DDSCL_EXCLUSIVE | DDSCL_ALLOWREBOOT)!=DD_OK)
  641.     return(0);
  642.  
  643. // set the display mode
  644. if (lpdd->SetDisplayMode(SCREEN_WIDTH,SCREEN_HEIGHT,SCREEN_BPP,0,0)!=DD_OK)
  645.    return(0);
  646.  
  647. // Create the primary surface
  648. memset(&ddsd,0,sizeof(ddsd));
  649. ddsd.dwSize = sizeof(ddsd);
  650. ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
  651.  
  652. // we need to let dd know that we want a complex 
  653. // flippable surface structure, set flags for that
  654. ddsd.ddsCaps.dwCaps = 
  655.   DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX;
  656.  
  657. // set the backbuffer count to 1
  658. ddsd.dwBackBufferCount = 1;
  659.  
  660. // create the primary surface
  661. lpdd->CreateSurface(&ddsd,&lpddsprimary,NULL);
  662.  
  663. // query for the backbuffer i.e the secondary surface
  664. ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
  665. lpddsprimary->GetAttachedSurface(&ddscaps,&lpddsback);
  666.  
  667. // create and attach palette
  668.  
  669. // create palette data
  670. // first clear out all the entries, defensive programming
  671. memset(palette,0,256*sizeof(PALETTEENTRY));
  672.  
  673. // create a R,G,B,GR gradient palette
  674. for (index=0; index<256; index++)
  675.     {
  676.     palette[index].peRed = rand()%256;
  677.     palette[index].peGreen = rand()%256;
  678.     palette[index].peBlue = rand()%256;
  679.     // set flags
  680.     palette[index].peFlags = PC_NOCOLLAPSE;
  681.     } // end for index
  682.  
  683.     palette[0].peRed = 0;
  684.     palette[0].peGreen = 0;
  685.     palette[0].peBlue =0;
  686.  
  687. // now create the palette object
  688. if (lpdd->CreatePalette(DDPCAPS_8BIT | DDPCAPS_INITIALIZE | DDPCAPS_ALLOW256,
  689.                          palette,&lpddpal,NULL)!=DD_OK)
  690.    return(0);
  691.  
  692. // attach the palette to the primary
  693. if (lpddsprimary->SetPalette(lpddpal)!=DD_OK)
  694.    return(0);
  695.  
  696. // now load the 8 bit color bitmap
  697. Load_Bitmap_File(&bitmap8bit, "ROCK8.BMP");
  698.  
  699. // now load the palette into the directdraw
  700. lpddpal->SetEntries(0,0,256,bitmap8bit.palette);
  701.  
  702. // create BOBs
  703. for (index=0; index<NUM_ASTEROIDS; index++)
  704.     {
  705.     // create the bob
  706.     Create_BOB(&asteroids[index],64,64,0,DDSCAPS_SYSTEMMEMORY);
  707.     
  708.     // extract a bitmap image for the BOB from the large bitmap
  709.     Load_BOB(&asteroids[index],&bitmap8bit,rand()%4,0,0);  
  710.  
  711.     // set random position and velocity
  712.     asteroids[index].x = rand()%SCREEN_WIDTH;
  713.     asteroids[index].y = rand()%SCREEN_HEIGHT;
  714.  
  715.     asteroids[index].xv = -8 + rand()%16;
  716.     asteroids[index].yv = -8 + rand()%16;
  717.  
  718.     } // end for index
  719.  
  720. // clear the primary and secondary surfaces
  721. memset(&ddbltfx,0,sizeof(ddbltfx));
  722. ddbltfx.dwSize = sizeof(ddbltfx);
  723. ddbltfx.dwFillColor = 0;
  724.  
  725. lpddsprimary->Blt(NULL,NULL,NULL,DDBLT_COLORFILL | DDBLT_WAIT,&ddbltfx); 
  726. lpddsback->Blt(NULL,NULL,NULL,DDBLT_COLORFILL | DDBLT_WAIT,&ddbltfx); 
  727.  
  728. // delete the bitmap 
  729. Unload_Bitmap_File(&bitmap8bit);
  730.  
  731. // return success
  732. return(1);
  733.  
  734. } // end Game_Init
  735.  
  736. ///////////////////////////////////////////////////////////
  737.  
  738. int Game_Shutdown(void *parms)
  739. {
  740. // this function is where you shutdown your game and
  741. // release all resources that you allocated
  742.  
  743. // delete bobs
  744. for (int index=0; index<NUM_ASTEROIDS; index++)
  745.     Destroy_BOB(&asteroids[index]);
  746.  
  747. // first release the secondary surface
  748. if (lpddsback!=NULL)
  749.    lpddsback->Release();
  750.  
  751. // now release the primary surface
  752. if (lpddsprimary!=NULL)
  753.    lpddsprimary->Release();
  754.        
  755. // release the directdraw object
  756. if (lpdd!=NULL)
  757.    lpdd->Release();
  758.  
  759. // return success
  760. return(1);
  761. } // end Game_Shutdown
  762.  
  763. ///////////////////////////////////////////////////////////
  764.  
  765. int Game_Main(void *parms)
  766. {
  767. // this is the workhorse of your game it will be called
  768. // continuously in real-time this is like main() in C
  769. // all the calls for you game go here!
  770. int index; // looping variable
  771.  
  772. // check of user is trying to exit
  773. if (KEY_DOWN(VK_ESCAPE) || KEY_DOWN(VK_SPACE))
  774.     PostMessage(main_window_handle, WM_DESTROY,0,0);
  775.  
  776. // clear secondary buffer
  777. memset(&ddbltfx,0,sizeof(ddbltfx));
  778. ddbltfx.dwSize = sizeof(ddbltfx);
  779. ddbltfx.dwFillColor = 0;
  780. lpddsback->Blt(NULL,NULL,NULL,DDBLT_COLORFILL | DDBLT_WAIT,&ddbltfx); 
  781.  
  782. // move asteroids
  783. for (index=0; index<NUM_ASTEROIDS; index++)
  784.     {
  785.     asteroids[index].x+=asteroids[index].xv;
  786.     asteroids[index].y+=asteroids[index].yv;
  787.     } // end for index
  788.  
  789. // check if asteroids are off screen boundaries
  790. for (index=0; index<NUM_ASTEROIDS; index++)
  791.     {
  792.     // x bounds
  793.     if (asteroids[index].x > SCREEN_WIDTH)
  794.        asteroids[index].x = -asteroids[index].width;
  795.     else
  796.     if (asteroids[index].x < -asteroids[index].width)
  797.         asteroids[index].x = SCREEN_WIDTH;
  798.  
  799.     // y bounds
  800.     if (asteroids[index].y > SCREEN_HEIGHT)
  801.         asteroids[index].y = -asteroids[index].height;
  802.     else
  803.     if (asteroids[index].y < -asteroids[index].height)
  804.        asteroids[index].y = SCREEN_HEIGHT;
  805.     } // end for index
  806.  
  807. // draw all asteroids
  808. for (index=0; index<NUM_ASTEROIDS; index++)
  809.      Draw_BOB(&asteroids[index], lpddsback);
  810.  
  811. // flip pages
  812. while(lpddsprimary->Flip(NULL, DDFLIP_WAIT)!=DD_OK);
  813.  
  814. // slow things down
  815. Sleep(30);
  816.  
  817. // return success
  818. return(1);
  819.  
  820. } // end Game_Main
  821.  
  822.