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

  1. // PROG9_5.CPP - creates a palett, draws color bars
  2. // and animated them with color rotation
  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  640              // size of window
  31. #define WINDOW_HEIGHT 480
  32. #define SCREEN_WIDTH  640              // size of screen
  33. #define SCREEN_HEIGHT 480
  34. #define SCREEN_BPP    8                // bits per pixel
  35. #define MAX_COLORS    256              // maximum colors
  36.  
  37. // MACROS /////////////////////////////////////////////////
  38.  
  39. // these read the keyboard asynchronously
  40. #define KEY_DOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)
  41. #define KEY_UP(vk_code)   ((GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1)
  42.  
  43. // this builds a 16 bit color value in 5.5.5 format (1-bit alpha mode)
  44. #define _RGB16BIT555(r,g,b) ((b & 31) + ((g & 31) << 5) + ((r & 31) << 10))
  45.  
  46. // this builds a 16 bit color value in 5.6.5 format (green dominate mode)
  47. #define _RGB16BIT565(r,g,b) ((b & 31) + ((g & 63) << 5) + ((r & 31) << 11))
  48.  
  49.  
  50. // TYPES //////////////////////////////////////////////////
  51.  
  52. typedef unsigned short USHORT;
  53. typedef unsigned short WORD;
  54. typedef unsigned char  UCHAR;
  55. typedef unsigned char  BYTE;
  56.  
  57. // PROTOTYPES /////////////////////////////////////////////
  58.  
  59. int Game_Init(void *parms=NULL);
  60. int Game_Shutdown(void *parms=NULL);
  61. int Game_Main(void *parms=NULL);
  62. void Draw_Hline(int xs, int xe, int y, int color, UCHAR *vbuffer, int bytes_per_line);
  63.  
  64. // GLOBALS ////////////////////////////////////////////////
  65.  
  66. HWND main_window_handle = NULL; // save the window handle
  67. HINSTANCE main_instance = NULL; // save the instance
  68. char buffer[80];                // used to print text
  69.  
  70. LPDIRECTDRAW7        lpdd         = NULL;  // dd object
  71. LPDIRECTDRAWSURFACE7 lpddsprimary = NULL;  // dd primary surface
  72. LPDIRECTDRAWSURFACE7 lpddsback    = NULL;  // dd back surface
  73. LPDIRECTDRAWPALETTE  lpddpal      = NULL;  // a pointer to the created dd palette
  74. DDSURFACEDESC2       ddsd;                 // a direct draw surface description struct
  75. DDSCAPS2             ddscaps;              // a direct draw surface capabilities struct
  76. HRESULT              ddrval;               // result back from dd calls
  77. PALETTEENTRY         palette[MAX_COLORS];  // the color palette
  78.  
  79. // FUNCTIONS //////////////////////////////////////////////
  80.  
  81. LRESULT CALLBACK WindowProc(HWND hwnd, 
  82.                             UINT msg, 
  83.                             WPARAM wparam, 
  84.                             LPARAM lparam)
  85. {
  86. // this is the main message handler of the system
  87. PAINTSTRUCT    ps;           // used in WM_PAINT
  88. HDC            hdc;       // handle to a device context
  89.  
  90. // what is the message 
  91. switch(msg)
  92.     {    
  93.     case WM_CREATE: 
  94.         {
  95.         // do initialization stuff here
  96.         return(0);
  97.         } break;
  98.  
  99.     case WM_PAINT:
  100.          {
  101.          // start painting
  102.          hdc = BeginPaint(hwnd,&ps);
  103.  
  104.          // end painting
  105.          EndPaint(hwnd,&ps);
  106.          return(0);
  107.         } break;
  108.  
  109.     case WM_DESTROY: 
  110.         {
  111.         // kill the application            
  112.         PostQuitMessage(0);
  113.         return(0);
  114.         } break;
  115.  
  116.     default:break;
  117.  
  118.     } // end switch
  119.  
  120. // process any messages that we didn't take care of 
  121. return (DefWindowProc(hwnd, msg, wparam, lparam));
  122.  
  123. } // end WinProc
  124.  
  125. // WINMAIN ////////////////////////////////////////////////
  126.  
  127. int WINAPI WinMain(    HINSTANCE hinstance,
  128.                     HINSTANCE hprevinstance,
  129.                     LPSTR lpcmdline,
  130.                     int ncmdshow)
  131. {
  132.  
  133. WNDCLASS winclass;    // this will hold the class we create
  134. HWND     hwnd;        // generic window handle
  135. MSG         msg;        // generic message
  136. HDC      hdc;       // generic dc
  137. PAINTSTRUCT ps;     // generic paintstruct
  138.  
  139. // first fill in the window class stucture
  140. winclass.style            = CS_DBLCLKS | CS_OWNDC | 
  141.                           CS_HREDRAW | CS_VREDRAW;
  142. winclass.lpfnWndProc    = WindowProc;
  143. winclass.cbClsExtra        = 0;
  144. winclass.cbWndExtra        = 0;
  145. winclass.hInstance        = hinstance;
  146. winclass.hIcon            = LoadIcon(NULL, IDI_APPLICATION);
  147. winclass.hCursor        = LoadCursor(NULL, IDC_ARROW);
  148. winclass.hbrBackground    = (HBRUSH)GetStockObject(BLACK_BRUSH);
  149. winclass.lpszMenuName    = NULL; 
  150. winclass.lpszClassName    = WINDOW_CLASS_NAME;
  151.  
  152. // register the window class
  153. if (!RegisterClass(&winclass))
  154.     return(0);
  155.  
  156. // create the window, note the use of WS_POPUP
  157. if (!(hwnd = CreateWindow(WINDOW_CLASS_NAME, // class
  158.                           "WinX Game Console",     // title
  159.                           WS_POPUP | WS_VISIBLE,
  160.                            0,0,       // x,y
  161.                           WINDOW_WIDTH,  // width
  162.                           WINDOW_HEIGHT, // height
  163.                           NULL,       // handle to parent 
  164.                           NULL,       // handle to menu
  165.                           hinstance,// instance
  166.                           NULL)))    // creation parms
  167. return(0);
  168.  
  169. // save the window handle and instance in a global
  170. main_window_handle = hwnd;
  171. main_instance      = hinstance;
  172.  
  173. // perform all game console specific initialization
  174. Game_Init();
  175.  
  176. // enter main event loop
  177. while(1)
  178.     {
  179.     if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
  180.         { 
  181.         // test if this is a quit
  182.         if (msg.message == WM_QUIT)
  183.            break;
  184.     
  185.         // translate any accelerator keys
  186.         TranslateMessage(&msg);
  187.  
  188.         // send the message to the window proc
  189.         DispatchMessage(&msg);
  190.         } // end if
  191.     
  192.     // main game processing goes here
  193.     Game_Main();
  194.  
  195.     } // end while
  196.  
  197. // shutdown game and release all resources
  198. Game_Shutdown();
  199.  
  200. // return to Windows like this
  201. return(msg.wParam);
  202.  
  203. } // end WinMain
  204.  
  205. // WINX GAME PROGRAMMING CONSOLE FUNCTIONS ////////////////
  206.  
  207. int Game_Init(void *parms)
  208. {
  209. // this function is where you do all the initialization 
  210. // for your game
  211.  
  212. // create object and test for error
  213. if (DirectDrawCreateEx(NULL, (void **)&lpdd, IID_IDirectDraw7, NULL)!=DD_OK)
  214.    return(0);
  215.  
  216. // set cooperation level to windowed mode normal
  217. if (lpdd->SetCooperativeLevel(main_window_handle,
  218.            DDSCL_ALLOWMODEX | DDSCL_FULLSCREEN | 
  219.            DDSCL_EXCLUSIVE | DDSCL_ALLOWREBOOT)!=DD_OK)
  220.     return(0);
  221.  
  222. // set the display mode
  223. if (lpdd->SetDisplayMode(SCREEN_WIDTH,SCREEN_HEIGHT,SCREEN_BPP,0,0)!=DD_OK)
  224.    return(0);
  225.  
  226. // Create the primary surface
  227. memset(&ddsd,0,sizeof(ddsd));
  228. ddsd.dwSize         = sizeof(ddsd);
  229. ddsd.dwFlags        = DDSD_CAPS;
  230. ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
  231.  
  232. if (lpdd->CreateSurface(&ddsd,&lpddsprimary,NULL)!=DD_OK)
  233.    return(0);
  234.  
  235. // create palette data
  236. // first clear out all the entries, defensive programming
  237. memset(palette,0,256*sizeof(PALETTEENTRY));
  238.  
  239. // create a R,G,B,GR gradient palette
  240. for (int index=0; index<256; index++)
  241.     {
  242.     if (index < 64) // shades of red 
  243.         palette[index].peRed = index*4; 
  244.     else           // shades of green
  245.     if (index >=64 && index < 128) 
  246.         palette[index].peGreen = (index-64)*4;
  247.     else           // shades of blue
  248.     if (index >=128 && index < 192) 
  249.        palette[index].peBlue = (index-128)*4;
  250.     else           // shades of grey
  251.     if (index >=192 && index < 256) 
  252.         palette[index].peRed = palette[index].peGreen = 
  253.         palette[index].peBlue = (index-192)*4;
  254.  
  255.     // set flags
  256.     palette[index].peFlags = PC_NOCOLLAPSE;
  257.     } // end for index
  258.  
  259. // now create the palette object
  260. if (lpdd->CreatePalette(DDPCAPS_8BIT | DDPCAPS_INITIALIZE | DDPCAPS_ALLOW256,
  261.                          palette,&lpddpal,NULL)!=DD_OK)
  262.    return(0);
  263.  
  264. // attach the palette to the primary
  265. if (lpddsprimary->SetPalette(lpddpal)!=DD_OK)
  266.    return(0);
  267.  
  268. // return success
  269. return(1);
  270. } // end Game_Init
  271.  
  272. ///////////////////////////////////////////////////////////
  273.  
  274. int Game_Shutdown(void *parms)
  275. {
  276. // this function is where you shutdown your game and
  277. // release all resources that you allocated
  278.  
  279. // first release the palette
  280. if (lpddpal!=NULL)
  281.    lpddpal->Release();
  282.  
  283. // now release the primary surface
  284. if (lpddsprimary!=NULL)
  285.    lpddsprimary->Release();
  286.        
  287. // release the directdraw object
  288. if (lpdd!=NULL)
  289.    lpdd->Release();
  290.  
  291. // return success
  292. return(1);
  293. } // end Game_Shutdown
  294.  
  295. ///////////////////////////////////////////////////////////
  296.  
  297. int Game_Main(void *parms)
  298. {
  299. // this is the workhorse of your game it will be called
  300. // continuously in real-time this is like main() in C
  301. // all the calls for you game go here!
  302.  
  303. PALETTEENTRY work_colors[256]; // used to perform the algorithm   
  304.  
  305. // this will be aliased to the video memory
  306. UCHAR *video_buffer = NULL; 
  307.               
  308. // check of user is trying to exit
  309. if (KEY_DOWN(VK_ESCAPE) || KEY_DOWN(VK_SPACE))
  310.     PostMessage(main_window_handle, WM_DESTROY,0,0);
  311.  
  312. // draw the colored bars here
  313. // set up the surface description to lock the surface
  314. memset(&ddsd,0,sizeof(ddsd)); 
  315. ddsd.dwSize = sizeof(ddsd);
  316.  
  317. // lock the primary surface, note in a real game you would
  318. // do this once per frame
  319. lpddsprimary->Lock(NULL,&ddsd, 
  320.              DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT,NULL);
  321.  
  322. // get video pointer, we could have just as easily used
  323. // ddsd.lpSurface, but I like to alias the ptr
  324. video_buffer = (UCHAR *)ddsd.lpSurface;
  325.  
  326. // draw a collection of horizontal lines each with a different color
  327. // using a function defined below
  328. for (int y=0; y<SCREEN_HEIGHT; y++)
  329.     Draw_Hline(0,SCREEN_WIDTH-1, // starting and ending x
  330.                y,                // y position
  331.                y % MAX_COLORS,   // color of line
  332.                video_buffer,     // destination memory 
  333.                ddsd.lPitch);     // bytes per line
  334.  
  335. // unlock the surface, very important!
  336. lpddsprimary->Unlock(NULL);
  337.  
  338. // perform a color rotation on all 256 colors, the technique
  339. // is like taking all the 256 colors and shifting once to the
  340. // right (or left) and then taking the last color and pouring 
  341. // it into the first, in reality you would do this a little
  342. // differently, for example use a shadow data area to hold the
  343. // color rather than querrying them with GetEntries(), but this
  344. // is a good example of using GetEntries() and SetEntries()
  345. // notice we don't have to lock the primary display or anything
  346. // like that, note that these functions are very slow, better
  347. // to just change the entire palette at once!
  348.  
  349.  
  350. // get the color palette
  351. lpddpal->GetEntries(0,0,256,work_colors);
  352.  
  353. // shift and store at 1-255
  354. lpddpal->SetEntries(0,1,255,work_colors);
  355.  
  356. // now store color 255 at 0
  357. lpddpal->SetEntries(0,0,1,&work_colors[255]);
  358.  
  359.  
  360. // wait a sec
  361. Sleep(1);
  362.  
  363. // return success
  364. return(1);
  365. } // end Game_Main
  366.  
  367. ///////////////////////////////////////////////////////////
  368.  
  369. void Draw_Hline(int xs, int xe, int y, int color, UCHAR *vbuffer, int bytes_per_line)
  370. {
  371. // this function draws a horizontal line, in a 256 color mode, notice
  372. // that it takes into consideration the memory pitch of the mode
  373.  
  374. // compute starting video address of video line
  375. UCHAR *video_addr = vbuffer + y*bytes_per_line;
  376.  
  377. // now were on the correct video line, so draw the line
  378. // draw the line a byte at a time
  379. for (int x=xs; x<=xe; x++)
  380.     video_addr[x] = (UCHAR)color;
  381.  
  382. // or you could do this
  383. // memset((void *)(video_addr+xs),(UCHAR)col,xe-xs+1);
  384.  
  385. } // end Draw_Hline
  386.