Main.cpp
上传用户:sycq158
上传日期:2008-10-22
资源大小:15361k
文件大小:58k
源码类别:

游戏

开发平台:

Visual C++

  1. //-----------------------------------------------------------------------------
  2. // File: Main.cpp
  3. //
  4. //-----------------------------------------------------------------------------
  5. #define STRICT
  6. #include <windows.h>
  7. #include <ddraw.h>
  8. #include <dshow.h>
  9. #include <mmsystem.h>
  10. #include <math.h>
  11. #include <fstream>
  12. #include <list>
  13. #include "resource.h"
  14. #include "DSUtil.h"
  15. #include "ddutil.h"
  16. #include "Maze.h"
  17. #include "Sprite.h"
  18. #include "SpriteManager.h"
  19. #include "GameErrors.h"
  20. #include "InputLayer.h"
  21. #include "Keyboard.h"
  22. #include "ijl.h"  // Intel JPEG header file
  23. //#define DISPLAY_STATUS
  24. #undef DISPLAY_STATUS
  25. //-----------------------------------------------------------------------------
  26. // Defines, constants, and global variables
  27. //-----------------------------------------------------------------------------
  28. #define SAFE_DELETE(p)  { if(p) { delete (p);     (p)=NULL; } }
  29. #define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } }
  30. #define TITLE "Adventure in Abit"
  31. #define SPLASHFILENAME "AdvInAbat.jpg"
  32. #define CHOICEFILENAME "choose.jpg"
  33. #define GAMEOVERBADFILENAME "GameOver.jpg"
  34. #define GAMEOVERGOODFILENAME "Finish.jpg"
  35. #define SCREEN_WIDTH    1024
  36. #define SCREEN_HEIGHT   768
  37. #define SCREEN_BPP      16
  38. #define SPRITE_WIDTH    64
  39. #define SPRITE_HEIGHT   64
  40. #define MAZETEXTURE_WIDTH    32
  41. #define MAZETEXTURE_HEIGHT   32
  42. #define TYPE_PLAYER   1
  43. #define TYPE_ENEMY1 2
  44. #define TYPE_ENEMY2 3
  45. #define TYPE_ENEMY3 4
  46. #define TYPE_ENEMY4 5
  47. #define TYPE_POO    10
  48. #define TYPE_SPECIAL 11
  49. #define TYPE_BULLET  12
  50. #define ST_STAND_STILL 1 
  51. #define ST_WALK_UP     2
  52. #define ST_WALK_DOWN   3
  53. #define ST_WALK_LEFT   4
  54. #define ST_WALK_RIGHT  5
  55. #define ST_DEFAULT     6
  56. #define ST_KEY         7
  57. #define ST_DOOR        8
  58. #define ST_FOOD1       9
  59. #define ST_FOOD2       (ST_FOOD1+1)
  60. #define ST_FOOD3       (ST_FOOD1+2)
  61. #define ST_FOOD4       (ST_FOOD1+3)
  62. #define ST_FOOD5       (ST_FOOD1+4)
  63. #define ST_FOOD6       (ST_FOOD1+5)
  64. #define GAMESTATE_SPLASHSCREEN 0
  65. #define GAMESTATE_CHOICE       1
  66. #define GAMESTATE_RUNNING      2
  67. #define GAMESTATE_GAMEOVERBAD  3
  68. #define GAMESTATE_GAMEOVERGOOD 4
  69. #define POO_DELAY   500
  70. #define INVULNERABLE_DELAY  200
  71. #define NO_OF_LIFE     4
  72. #define NO_OF_SPECIALS 5
  73. #define GAMESTATUS_TEXT "Dead Pigs:%d Dead Enemies:%d"
  74. char g_szGameStatus[200];
  75. #define LIFE_LEFT_TEXT "Lives:%d"
  76. char g_szLifeLeft[100];
  77. #define GAMESCORE_TEXT "Score:%06d"
  78. char g_szScore[100];
  79. CDisplay*            g_pDisplay        = NULL;
  80. #ifdef DISPLAY_STATUS
  81. CSurface*            g_pTextSurface    = NULL;  
  82. #endif
  83. CSurface*            g_pLifeTextSurface = NULL;  
  84. CSurface*            g_pScoreTextSurface = NULL;  
  85. CSurface*            g_pLevelTextSurface = NULL;  
  86. CSurface*            g_pMazeSurface    = NULL;  
  87. CSurface*            g_pSpriteSurface  = NULL;
  88. CSurface*            g_pSplashSurface  = NULL;
  89. RECT                 g_rcWindow;            
  90. RECT                 g_rcViewport;          
  91. RECT                 g_rcScreen;            
  92. BOOL                 g_bWindowed   = false;  
  93. BOOL                 g_bActive     = FALSE;
  94. DWORD                g_dwLastTick;
  95. CMaze                g_Maze(MAKEINTRESOURCE(IDB_TEXTURE));
  96. CSprite              g_PigSprite;
  97. CSprite              g_RabbitSprite;
  98. CSprite              g_SheepSprite;
  99. CSprite*             g_pPlayerSprite = NULL;
  100. CSprite              g_Enemy1Sprite;
  101. CSprite              g_Enemy2Sprite;
  102. CSprite              g_Enemy3Sprite;
  103. CSprite              g_Enemy4Sprite;
  104. CSprite              g_Enemy5Sprite;
  105. CSprite              g_PigPooSprite;
  106. CSprite              g_RabbitPooSprite;
  107. CSprite              g_SheepPooSprite;
  108. CSprite*              g_pPooSprite= NULL;
  109. CSprite              g_SpecialSprite;
  110. CSprite              g_BulletSprite;
  111. CSpriteManager       g_EnemySpriteManager;
  112. CSound*              g_pSplashSound = NULL;
  113. CSound*              g_pPickupSound = NULL;
  114. CSoundManager*       g_pSoundManager = NULL;
  115. int                  g_nGameState = GAMESTATE_SPLASHSCREEN;
  116. int                  g_nPigDead = 0;
  117. int                  g_nEnemyDead = 0;
  118. long                 g_nPooDelay = 0;
  119. long                 g_nNoOfEnemies = 10;
  120. long                 g_nLivesLeft = NO_OF_LIFE;
  121. long                 g_nNoOfSpecials = NO_OF_SPECIALS;
  122. long                 g_nScore = 0;
  123. struct SLEVEL {
  124. char  szLevelFile[100];
  125. int   nNoOfEnemys;
  126. }* g_pLevel;
  127. long                 g_nNoOfLevels;
  128. long                 g_nCurrLevel=0;
  129. HINSTANCE g_hInstance;
  130. HWND      g_hMainWnd;
  131. //-----------------------------------------------------------------------------
  132. // Function-prototypes
  133. //-----------------------------------------------------------------------------
  134. LRESULT CALLBACK MainWndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam );
  135. HRESULT WinInit( HINSTANCE hInst, int nCmdShow, HWND* phWnd, HACCEL* phAccel );
  136. HRESULT InitDirectDraw( HWND hWnd );
  137. VOID    FreeDirectDraw();
  138. HRESULT InitDirectDrawMode( HWND hWnd, BOOL bWindowed );
  139. HRESULT ProcessNextFrame( HWND hWnd );
  140. HRESULT DisplayFrame();
  141. HRESULT RestoreSurfaces();
  142. bool LoadJPEG(bool bFromFile, LPCTSTR szName,  CSurface** ppSurface);
  143. void DisplaySplashScreen(bool bDisplay);
  144. void InitSprites();
  145. void InitLevel();
  146. void MoveCharacterRelative(long dX, long dY);
  147. struct SHandleInput: public iKeyboardReceiver
  148. {
  149. SHandleInput() {
  150. cInputLayer::Create( g_hInstance, g_hMainWnd, 
  151. true, true, false );
  152. Input()->GetKeyboard()->SetReceiver( this );
  153. }
  154. ~SHandleInput() {
  155. cInputLayer::Destroy();
  156. }
  157. void KeyUp( int key ) 
  158. {
  159. switch(g_nGameState) 
  160. {
  161. case GAMESTATE_SPLASHSCREEN: 
  162. {
  163. switch( key )
  164. {
  165. case DIK_SPACE:
  166. {
  167. g_nGameState=GAMESTATE_CHOICE;
  168. g_pSplashSound->Stop();
  169. LoadJPEG(true, CHOICEFILENAME,  &g_pSplashSurface);
  170. break;
  171. }
  172. }
  173. }
  174. break;
  175. case GAMESTATE_CHOICE:
  176. {
  177. bool bKeyHit = false;
  178. switch( key )
  179. {
  180. case DIK_1: g_pPlayerSprite = &g_PigSprite; 
  181. g_pPooSprite = &g_PigPooSprite;
  182. bKeyHit = true; break;
  183. case DIK_2: g_pPlayerSprite = &g_RabbitSprite;
  184. g_pPooSprite = &g_RabbitPooSprite;
  185. bKeyHit = true;break;
  186. case DIK_3: g_pPlayerSprite = &g_SheepSprite; 
  187. g_pPooSprite = &g_SheepPooSprite;
  188. bKeyHit = true; break;
  189. }
  190. if (bKeyHit) {
  191. g_nGameState=GAMESTATE_RUNNING;
  192. InitLevel();
  193. }
  194. }
  195. break;
  196. case GAMESTATE_RUNNING: 
  197. {
  198. switch( key )
  199. {
  200. // move up
  201. case DIK_UP:
  202. case DIK_NUMPAD8:
  203. // move down
  204. case DIK_DOWN:
  205. case DIK_NUMPAD2:
  206. // turn right
  207. case DIK_RIGHT:
  208. case DIK_NUMPAD6:
  209. // turn left
  210. case DIK_LEFT:
  211. case DIK_NUMPAD4:
  212. g_pPlayerSprite->SetState(ST_STAND_STILL);
  213. g_pPlayerSprite->m_Movement.m_dx = g_pPlayerSprite->m_Movement.m_dy =0;
  214. break;
  215. }
  216. }
  217. break;
  218. case GAMESTATE_GAMEOVERGOOD: 
  219. case GAMESTATE_GAMEOVERBAD: 
  220. {
  221. switch( key )
  222. {
  223. case DIK_SPACE:
  224. {
  225. g_nGameState=GAMESTATE_SPLASHSCREEN;
  226. g_nLivesLeft = NO_OF_LIFE;
  227. g_nScore=0;
  228. g_nCurrLevel=0;
  229. break;
  230. }
  231. }
  232. }
  233. break;
  234. }
  235. }
  236. void KeyDown( int key )
  237. {
  238. switch(g_nGameState) {
  239. case GAMESTATE_RUNNING: 
  240. {
  241. switch( key )
  242. {
  243. // move up
  244. case DIK_UP:
  245. case DIK_NUMPAD8:
  246. {
  247. g_pPlayerSprite->SetState(ST_WALK_UP);
  248. g_pPlayerSprite->m_Movement.m_dy = -2;
  249. g_pPlayerSprite->m_Movement.m_dx = 0;
  250. break;
  251. }
  252. // move down
  253. case DIK_DOWN:
  254. case DIK_NUMPAD2:
  255. {
  256. g_pPlayerSprite->SetState(ST_WALK_DOWN);
  257. g_pPlayerSprite->m_Movement.m_dy = 2;
  258. g_pPlayerSprite->m_Movement.m_dx = 0;
  259. break;
  260. }
  261. // Shoot
  262. case DIK_SPACE:
  263. {
  264. if (g_nPooDelay == 0 && g_pPlayerSprite->GetState()!= ST_KILL) {
  265. RECT rc = g_pPlayerSprite->GetRect();
  266. g_pPooSprite->MoveTo(rc.left,rc.top);
  267. g_nPooDelay = POO_DELAY;
  268. g_pPooSprite->SetState(ST_DEFAULT);
  269. }
  270. break;
  271. }
  272. // turn right
  273. case DIK_RIGHT:
  274. case DIK_NUMPAD6:
  275. {
  276. g_pPlayerSprite->SetState(ST_WALK_RIGHT); 
  277. g_pPlayerSprite->m_Movement.m_dx = 2;
  278. g_pPlayerSprite->m_Movement.m_dy = 0;
  279. break;
  280. }
  281. // turn left
  282. case DIK_LEFT:
  283. case DIK_NUMPAD4:
  284. {
  285. g_pPlayerSprite->SetState(ST_WALK_LEFT);
  286. g_pPlayerSprite->m_Movement.m_dx = -2;
  287. g_pPlayerSprite->m_Movement.m_dy = 0;
  288. break;
  289. }
  290. }
  291. }
  292. }
  293. }
  294. } *  g_pHandleInput = NULL;
  295. //-----------------------------------------------------------------------------
  296. // Name: WinMain()
  297. // Desc: Entry point to the program. Initializes everything and calls
  298. //       UpdateFrame() when idle from the message pump.
  299. //-----------------------------------------------------------------------------
  300. int APIENTRY WinMain( HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR pCmdLine, int nCmdShow )
  301. {
  302.     MSG    msg;
  303.     HWND   hWnd;
  304.     HACCEL hAccel;
  305.     srand( GetTickCount() );
  306. wsprintf((char*)g_szGameStatus, (char*)GAMESTATUS_TEXT,0,0);
  307. wsprintf((char*)g_szLifeLeft, (char*)LIFE_LEFT_TEXT,g_nLivesLeft -1);
  308. wsprintf((char*)g_szScore, (char*)GAMESCORE_TEXT,g_nScore);
  309. g_hInstance = hInst;
  310. char szName[200];
  311. std::fstream LevelData("config.txt",std::ios::in );
  312.     LevelData.getline(szName,200);
  313. // Read number of horizontal lines
  314. LevelData >> g_nNoOfLevels;   // Number of Horizontal rows
  315. g_pLevel = new SLEVEL[g_nNoOfLevels];
  316. if (g_pLevel == NULL)
  317. return -1;
  318. for (int nI = 0; nI < g_nNoOfLevels; nI++) {
  319. LevelData >> g_pLevel[nI].szLevelFile;
  320. LevelData >> g_pLevel[nI].nNoOfEnemys;
  321. }
  322.     if( FAILED( WinInit( hInst, nCmdShow, &hWnd, &hAccel ) ) )
  323.         return FALSE;
  324.     if( FAILED( InitDirectDraw( hWnd ) ) )
  325.     {
  326.         MessageBox( hWnd, TEXT("DirectDraw init failed. ")
  327. TEXT("The program will now exit. "), TEXT("Maze Test program"), 
  328. MB_ICONERROR | MB_OK );
  329.         return FALSE;
  330.     }
  331. InitSprites();
  332.     g_dwLastTick = timeGetTime();
  333.     while( TRUE )
  334.     {
  335.         // Look for messages, if none are found then 
  336.         // update the state and display it
  337.         if( PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE ) )
  338.         {
  339.             if( 0 == GetMessage(&msg, NULL, 0, 0 ) )
  340.             {
  341.                 // WM_QUIT was posted, so exit
  342. FreeDirectDraw();
  343. CoUninitialize();
  344. delete[] g_pLevel;
  345.                 return (int)msg.wParam;
  346.             }
  347.             // Translate and dispatch the message
  348.             if( 0 == TranslateAccelerator( hWnd, hAccel, &msg ) )
  349.             {
  350.                 TranslateMessage( &msg ); 
  351.                 DispatchMessage( &msg );
  352.             }
  353.         }
  354.         else
  355.         {
  356.             if( g_bActive )
  357.             {
  358.                 // Move the sprites, blt them to the back buffer, then 
  359.                 // flip or blt the back buffer to the primary buffer
  360.                 if( FAILED( ProcessNextFrame( hWnd ) ) )
  361.                 {
  362.                     SAFE_DELETE( g_pDisplay );
  363.                     MessageBox( hWnd, TEXT("Displaying the next frame failed. ")
  364. TEXT("The program will now exit. "), TEXT("Adv In Abt"), 
  365. MB_ICONERROR | MB_OK );
  366.                     return FALSE;
  367.                 }
  368.             }
  369.             else
  370.             {
  371.                 // Go to sleep if we have nothing else to do
  372.                 WaitMessage();
  373.                 // Ignore time spent inactive 
  374.                 g_dwLastTick = timeGetTime();
  375.             }
  376.         }
  377.     }
  378. }
  379. //-----------------------------------------------------------------------------
  380. // Name: WinInit()
  381. // Desc: Init the window
  382. //-----------------------------------------------------------------------------
  383. HRESULT WinInit( HINSTANCE hInst, int nCmdShow, HWND* phWnd, HACCEL* phAccel )
  384. {
  385.     WNDCLASSEX wc;
  386.     HWND       hWnd;
  387.     HACCEL     hAccel;
  388.     // Register the window class
  389.     wc.cbSize        = sizeof(wc);
  390.     wc.lpszClassName = TEXT("AdvInAbatWndClass");
  391.     wc.lpfnWndProc   = MainWndProc;
  392.     wc.style         = CS_VREDRAW | CS_HREDRAW;
  393.     wc.hInstance     = hInst;
  394.     wc.hIcon         = LoadIcon( hInst, MAKEINTRESOURCE(IDI_MAIN) );
  395.     wc.hIconSm       = LoadIcon( hInst, MAKEINTRESOURCE(IDI_MAIN) );
  396.     wc.hCursor       = LoadCursor( NULL, IDC_ARROW );
  397.     wc.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
  398.     wc.lpszMenuName  = 0;//MAKEINTRESOURCE(IDR_MENU);
  399.     wc.cbClsExtra    = 0;
  400.     wc.cbWndExtra    = 0;
  401.     if( RegisterClassEx( &wc ) == 0 ) {
  402. LPVOID lpMsgBuf;
  403. FormatMessage( 
  404. FORMAT_MESSAGE_ALLOCATE_BUFFER | 
  405. FORMAT_MESSAGE_FROM_SYSTEM | 
  406. FORMAT_MESSAGE_IGNORE_INSERTS,
  407. NULL,
  408. GetLastError(),
  409. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
  410. (LPTSTR) &lpMsgBuf,
  411. 0,
  412. NULL 
  413. );
  414. OutputDebugString( (LPCTSTR)lpMsgBuf);
  415. // Free the buffer.
  416. LocalFree( lpMsgBuf );
  417.         return E_FAIL;
  418. }
  419.     // Load keyboard accelerators
  420.     hAccel = LoadAccelerators( hInst, MAKEINTRESOURCE(IDR_MAIN_ACCEL) );
  421.     // Calculate the proper size for the window given a client of 640x480
  422.     DWORD dwFrameWidth    = GetSystemMetrics( SM_CXSIZEFRAME );
  423.     DWORD dwFrameHeight   = GetSystemMetrics( SM_CYSIZEFRAME );
  424.     DWORD dwMenuHeight    = GetSystemMetrics( SM_CYMENU );
  425.     DWORD dwCaptionHeight = GetSystemMetrics( SM_CYCAPTION );
  426.     DWORD dwWindowWidth   = SCREEN_WIDTH  + dwFrameWidth * 2;
  427.     DWORD dwWindowHeight  = SCREEN_HEIGHT + dwFrameHeight * 2 + 
  428. dwMenuHeight + dwCaptionHeight;
  429.     // Create and show the main window
  430.     DWORD dwStyle = WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX;
  431.     hWnd = CreateWindowEx( 0, TEXT("AdvInAbatWndClass"), 
  432. TEXT("Maze Test program"),
  433. dwStyle, CW_USEDEFAULT, CW_USEDEFAULT,
  434. dwWindowWidth, dwWindowHeight, NULL, NULL, hInst, NULL );
  435.     if( hWnd == NULL )
  436. return E_FAIL;
  437.     ShowWindow( hWnd, nCmdShow );
  438.     UpdateWindow( hWnd );
  439.     // Save the window size/pos for switching modes
  440.     GetWindowRect( hWnd, &g_rcWindow );
  441.     *phWnd   = hWnd;
  442.     *phAccel = hAccel;
  443. g_hMainWnd = hWnd;
  444.     return S_OK;
  445. }
  446. HFONT GetGameFont()
  447. {
  448. HFONT      hFont ;
  449. LOGFONT    lf ;
  450. lf.lfHeight         = 40;
  451. lf.lfWidth          = 20;
  452. lf.lfEscapement     = 0 ;
  453. lf.lfOrientation    = 0 ;
  454. lf.lfWeight         = 0 ;
  455. lf.lfItalic         = false ; 
  456. lf.lfUnderline      = false; 
  457. lf.lfStrikeOut      = false; 
  458. lf.lfCharSet        = DEFAULT_CHARSET ;
  459. lf.lfOutPrecision   = 0 ;
  460. lf.lfClipPrecision  = 0 ;
  461. lf.lfQuality        = 0 ;
  462. lf.lfPitchAndFamily = 0 ;
  463. lstrcpy (lf.lfFaceName, "Times New Roman") ;
  464. hFont = CreateFontIndirect (&lf) ;
  465. // hfont = (HFONT)GetStockObject(ANSI_VAR_FONT); 
  466. return hFont;
  467. }
  468. //-----------------------------------------------------------------------------
  469. // Name: InitDirectDraw()
  470. // Desc: Create the DirectDraw object, and init the surfaces
  471. //-----------------------------------------------------------------------------
  472. HRESULT InitDirectDraw( HWND hWnd )
  473. {
  474.     HRESULT hr;
  475.     // Initialize all the surfaces we need
  476.     if( FAILED( hr = InitDirectDrawMode( hWnd, g_bWindowed ) ) )
  477.         return hr;
  478.     // Create a static IDirectSound in the CSound class.  
  479.     // Set coop level to DSSCL_PRIORITY, and set primary buffer 
  480.     // format to stereo, 22kHz and 16-bit output.
  481.     g_pSoundManager = new CSoundManager();
  482.     if( FAILED(hr= g_pSoundManager->Initialize( hWnd, DSSCL_PRIORITY, 2, 22050, 16 ) ) )
  483.     {
  484.         MessageBox( 0, "Error initializing DirectSound.  Game will now exit.", 
  485. "Game", MB_OK | MB_ICONERROR );
  486.         return hr;
  487.     }
  488. g_pSoundManager->Create(&g_pPickupSound,"PickUp");
  489. g_pHandleInput = new SHandleInput();
  490.     return S_OK;
  491. }
  492. //-----------------------------------------------------------------------------
  493. // Name: InitDirectDrawMode()
  494. // Desc: Called when the user wants to toggle between full-screen and windowed 
  495. //       to create all the needed DDraw surfaces and set the coop level
  496. //-----------------------------------------------------------------------------
  497. HRESULT InitDirectDrawMode( HWND hWnd, BOOL bWindowed )
  498. {
  499.     HRESULT         hr;
  500.     LPDIRECTDRAWPALETTE pDDPal   = NULL; 
  501.     // Release all existing surfaces
  502. SAFE_DELETE( g_pMazeSurface);  
  503. #ifdef DISPLAY_STATUS
  504.     SAFE_DELETE( g_pTextSurface );
  505. #endif
  506. SAFE_DELETE( g_pLifeTextSurface );
  507. SAFE_DELETE( g_pScoreTextSurface );
  508. SAFE_DELETE( g_pLevelTextSurface );
  509. SAFE_DELETE( g_pSpriteSurface );
  510. SAFE_DELETE ( g_pSplashSurface);
  511. SAFE_DELETE( g_pDisplay );
  512.     //在满屏模式和窗口模式下,主页面和后台页面的创建方式是不同的
  513.     g_pDisplay = new CDisplay();
  514. //窗口模式
  515.     if( bWindowed )
  516.     {
  517.         if( FAILED( hr = g_pDisplay->CreateWindowedDisplay( hWnd, SCREEN_WIDTH, 
  518. SCREEN_HEIGHT ) ) )
  519.             return hr;
  520.         // 在窗口方式中添加系统菜单
  521.         DWORD dwStyle = GetWindowLong( hWnd, GWL_STYLE );
  522.         dwStyle |= WS_SYSMENU;
  523.         SetWindowLong( hWnd, GWL_STYLE, dwStyle );
  524.         // Show the menu in windowed mode 
  525. #ifdef _WIN64
  526.         HINSTANCE hInst = (HINSTANCE) GetWindowLongPtr( hWnd, GWLP_HINSTANCE );
  527. #else
  528.         HINSTANCE hInst = (HINSTANCE) GetWindowLong( hWnd, GWL_HINSTANCE );
  529. #endif
  530.         HMENU hMenu = LoadMenu( hInst, MAKEINTRESOURCE( IDR_MENU ) );
  531.         SetMenu( hWnd, hMenu );
  532.     }
  533.     else//满屏显示
  534.     {
  535.         if( FAILED( hr = g_pDisplay->CreateFullScreenDisplay( hWnd, SCREEN_WIDTH, 
  536. SCREEN_HEIGHT, SCREEN_BPP ) ) )
  537.         {
  538.             MessageBox( hWnd, TEXT("This display card does not support 640x480x8. "),
  539. TEXT("DirectDraw Sample"), MB_ICONERROR | MB_OK );
  540.             return hr;
  541.         }
  542.         // 无效菜单
  543.         SetMenu( hWnd, NULL );
  544.         // 从窗口方式中删除系统菜单
  545. /*
  546.         DWORD dwStyle = GetWindowLong( hWnd, GWL_STYLE );
  547.         dwStyle &= ~WS_SYSMENU;
  548.         SetWindowLong( hWnd, GWL_STYLE, dwStyle );       
  549. */
  550.     }
  551. // 创建一个页面,在上面绘制文本
  552. #ifdef DISPLAY_STATUS
  553. if( FAILED( hr = g_pDisplay->CreateSurfaceFromText( &g_pTextSurface, NULL, (char*)g_szGameStatus, 
  554. RGB(0,0,0), RGB(255, 255, 0) ) ) )
  555. return hr;
  556. #endif
  557. HFONT hFont = GetGameFont();
  558. if( FAILED( hr = g_pDisplay->CreateSurfaceFromText( &g_pLifeTextSurface, hFont, (char*)g_szLifeLeft, 
  559. RGB(0,0,0), RGB(255, 255, 0) ) ) )
  560. return hr;
  561. if( FAILED( hr = g_pDisplay->CreateSurfaceFromText( &g_pScoreTextSurface, hFont, (char*)g_szScore, 
  562. RGB(0,0,0), RGB(255, 255, 0) ) ) )
  563. return hr;
  564.     // Create a surface, and draw a bitmap resource on it.  The surface must 
  565.     // be newly created every time the screen mode is switched since it 
  566.     // uses the pixel format of the primary surface
  567. // Create a surface, and draw text to it.  
  568. if( FAILED( hr = g_pDisplay->CreateSurface( &g_pMazeSurface, SCREEN_WIDTH, SCREEN_HEIGHT) ))
  569. return hr;
  570. if( FAILED( hr = g_pDisplay->CreateSurfaceFromBitmap( &g_pSpriteSurface, MAKEINTRESOURCE(IDB_SPRITE),0, 0) ))
  571. return hr;
  572. g_pSpriteSurface->SetColorKey(RGB(0,0,0));
  573. g_Maze.Draw(g_pMazeSurface);
  574. if (g_nGameState == GAMESTATE_SPLASHSCREEN) {
  575. LoadJPEG(true, SPLASHFILENAME,  &g_pSplashSurface);
  576. }
  577. if (g_nGameState == GAMESTATE_CHOICE) {
  578. LoadJPEG(true, CHOICEFILENAME,  &g_pSplashSurface);
  579. }
  580. if (g_nGameState == GAMESTATE_GAMEOVERGOOD) {
  581. LoadJPEG(true, GAMEOVERGOODFILENAME,  &g_pSplashSurface);
  582. }
  583. if (g_nGameState == GAMESTATE_GAMEOVERBAD) {
  584. LoadJPEG(true, GAMEOVERBADFILENAME,  &g_pSplashSurface);
  585. }
  586. if (g_nGameState == GAMESTATE_RUNNING){
  587. g_pDisplay->CreateSurfaceFromText( &g_pLevelTextSurface, hFont, g_Maze.GetName(), 
  588. RGB(0,0,0), RGB(255, 255, 0) ) ;
  589. }
  590. DeleteObject(hFont);
  591.     return S_OK;
  592. }
  593. inline bool IsHit(RECT& rc)
  594. {
  595. return g_Maze.IsHit(rc);
  596. }
  597. void BulletFindPath(CSprite* pSprite)
  598. {
  599. pSprite->SetState(ST_KILL);
  600. }
  601. void FindPath(CSprite* pSprite)
  602. {
  603. int nH = rand()%2;
  604. int nV = rand()%2;
  605. int nNRnd = rand()%3;
  606. if (nNRnd) {
  607. if (abs(g_pPlayerSprite->m_ptLocation.x - pSprite->m_ptLocation.x) > 
  608. abs(g_pPlayerSprite->m_ptLocation.y - pSprite->m_ptLocation.y))
  609. {
  610. pSprite->m_Movement.m_dy = 0;
  611. if (g_pPlayerSprite->m_ptLocation.x < pSprite->m_ptLocation.x) {
  612. pSprite->m_Movement.m_dx= -1 * (rand()%2+1);
  613. pSprite->SetState(ST_WALK_LEFT);
  614. } else {
  615. pSprite->m_Movement.m_dx= 1 * (rand()%2+1);
  616. pSprite->SetState(ST_WALK_RIGHT);
  617. }
  618. } else {
  619. pSprite->m_Movement.m_dx = 0;
  620. if (g_pPlayerSprite->m_ptLocation.y < pSprite->m_ptLocation.y) {
  621. pSprite->m_Movement.m_dy= -1 * (rand()%2+1);
  622. pSprite->SetState(ST_WALK_UP);
  623. } else {
  624. pSprite->m_Movement.m_dy= 1 * (rand()%2+1);
  625. pSprite->SetState(ST_WALK_DOWN);
  626. }
  627. }
  628. } else {
  629. if (nV) {
  630. pSprite->m_Movement.m_dx = 0;
  631. if (nH) {
  632. pSprite->m_Movement.m_dy = 1 * (rand()%2+1);
  633. pSprite->SetState(ST_WALK_DOWN);
  634. } else {
  635. pSprite->m_Movement.m_dy = -1 * (rand()%2+1);
  636. pSprite->SetState(ST_WALK_UP);
  637. }
  638. } else {
  639. pSprite->m_Movement.m_dy = 0;
  640. if (nH) {
  641. pSprite->m_Movement.m_dx = 1 * (rand()%2+1);
  642. pSprite->SetState(ST_WALK_RIGHT);
  643. } else {
  644. pSprite->m_Movement.m_dx = -1 * (rand()%2+1);
  645. pSprite->SetState(ST_WALK_LEFT);
  646. }
  647. }
  648. }
  649. if (pSprite->GetType() == TYPE_ENEMY4) {
  650. if (g_BulletSprite.GetState() == ST_DEAD && pSprite->GetState() != ST_KILL 
  651. && pSprite->GetState() != ST_DEAD) {
  652. RECT rc = pSprite->GetRect();
  653. g_BulletSprite.MoveTo(rc.left,rc.top);
  654. g_BulletSprite.SetState(ST_DEFAULT);
  655. switch (pSprite->GetState()) {
  656. case ST_WALK_UP:
  657. g_BulletSprite.m_Movement.m_dx =0;
  658. g_BulletSprite.m_Movement.m_dy = -3;
  659. break;
  660. case ST_WALK_DOWN:
  661. g_BulletSprite.m_Movement.m_dx =0;
  662. g_BulletSprite.m_Movement.m_dy = 3;
  663. break;
  664. case ST_WALK_LEFT:
  665. g_BulletSprite.m_Movement.m_dx =-3;
  666. g_BulletSprite.m_Movement.m_dy = 0;
  667. break;
  668. case ST_WALK_RIGHT:
  669. g_BulletSprite.m_Movement.m_dx =3;
  670. g_BulletSprite.m_Movement.m_dy = 0;
  671. break;
  672. }
  673. }
  674. }
  675. }
  676. void DeadPig(CSprite* pSprite)
  677. {
  678. ++g_nPigDead;
  679. --g_nLivesLeft;
  680. #ifdef DISPLAY_STATUS
  681. wsprintf((char*)g_szGameStatus, (char*)GAMESTATUS_TEXT, g_nPigDead, g_nEnemyDead);
  682.     SAFE_DELETE( g_pTextSurface );
  683.     g_pDisplay->CreateSurfaceFromText( &g_pTextSurface, NULL, (char*)g_szGameStatus, 
  684. RGB(0,0,0), RGB(255, 255, 0) );
  685. #endif
  686. SAFE_DELETE( g_pLifeTextSurface );
  687. wsprintf((char*)g_szLifeLeft, (char*)LIFE_LEFT_TEXT, g_nLivesLeft-1);
  688. HFONT hFont = GetGameFont();
  689.     g_pDisplay->CreateSurfaceFromText( &g_pLifeTextSurface, hFont , (char*)g_szLifeLeft, 
  690. RGB(0,0,0), RGB(255, 255, 0) );
  691. DeleteObject(hFont);
  692. g_pPlayerSprite->MoveTo(1 * MAZETEXTURE_WIDTH, 19 * MAZETEXTURE_HEIGHT);
  693. g_pPlayerSprite->SetState(ST_WALK_UP);
  694. g_pPlayerSprite->m_Movement.m_nInvulnerable=INVULNERABLE_DELAY;
  695. if (g_nLivesLeft == 0) {
  696. g_nLivesLeft = NO_OF_LIFE;
  697. g_nGameState = GAMESTATE_GAMEOVERBAD;
  698. LoadJPEG(true, GAMEOVERBADFILENAME,  &g_pSplashSurface);
  699. }
  700. }
  701. void DeadEnemy(CSprite* pSprite)
  702. {
  703. ++g_nEnemyDead;
  704. #ifdef DISPLAY_STATUS
  705. wsprintf((char*)g_szGameStatus, (char*)GAMESTATUS_TEXT, g_nPigDead, g_nEnemyDead);
  706.     SAFE_DELETE( g_pTextSurface );
  707.     g_pDisplay->CreateSurfaceFromText( &g_pTextSurface, NULL, (char*)g_szGameStatus, 
  708. RGB(0,0,0), RGB(255, 255, 0) );
  709. #endif
  710. g_nScore += pSprite->m_nPoints;
  711. SAFE_DELETE( g_pScoreTextSurface );
  712. wsprintf((char*)g_szScore, (char*)GAMESCORE_TEXT, g_nScore);
  713. HFONT hFont = GetGameFont();
  714.     g_pDisplay->CreateSurfaceFromText( &g_pScoreTextSurface, hFont, (char*)g_szScore, 
  715. RGB(0,0,0), RGB(255, 255, 0) );
  716. DeleteObject(hFont);
  717. if (g_nNoOfEnemies) {
  718. g_nNoOfEnemies--;
  719. pSprite->SetState(ST_WALK_LEFT);
  720. POINT pt = g_Maze.GetRandDeployPoint();
  721. pt.x *= MAZETEXTURE_WIDTH;
  722. pt.y *= MAZETEXTURE_HEIGHT;
  723. pSprite->MoveTo(pt);
  724. (*pSprite->m_Movement.m_pfnFindPath)(pSprite);
  725. pSprite->m_Movement.m_nInvulnerable=INVULNERABLE_DELAY;
  726. }
  727. }
  728. bool KillSpecial(CSprite* pSprite)
  729. {
  730. if (pSprite->GetState() == ST_DOOR) {
  731. InitLevel();
  732. return false;
  733. }
  734. return true;
  735. }
  736. void DeadSpecial(CSprite* pSprite)
  737. {
  738. static long nSpecialState = ST_FOOD1;
  739. g_nScore += pSprite->m_nPoints;
  740. SAFE_DELETE( g_pScoreTextSurface );
  741. wsprintf((char*)g_szScore, (char*)GAMESCORE_TEXT, g_nScore);
  742. HFONT hFont = GetGameFont();
  743. g_pDisplay->CreateSurfaceFromText( &g_pScoreTextSurface, hFont, (char*)g_szScore, 
  744. RGB(0,0,0), RGB(255, 255, 0) );
  745. DeleteObject(hFont);
  746. if (g_nNoOfSpecials) {
  747. pSprite->SetState(rand()%6 + ST_FOOD1);
  748. POINT pt = g_Maze.GetRandDeployPoint();
  749. pt.x *= MAZETEXTURE_WIDTH;
  750. pt.y *= MAZETEXTURE_HEIGHT;
  751. pSprite->MoveTo(pt);
  752. nSpecialState = ST_FOOD1;
  753. --g_nNoOfSpecials;
  754. } else {
  755. switch (nSpecialState) {
  756. case ST_FOOD1:
  757. pSprite->SetState(ST_KEY);
  758. POINT pt = g_Maze.GetRandDeployPoint();
  759. pt.x *= MAZETEXTURE_WIDTH;
  760. pt.y *= MAZETEXTURE_HEIGHT;
  761. pSprite->MoveTo(pt);
  762. nSpecialState = ST_KEY;
  763. break;
  764. case ST_KEY:
  765. pSprite->SetState(ST_DOOR);
  766. pt = g_Maze.GetRandDeployPoint();
  767. pt.x *= MAZETEXTURE_WIDTH;
  768. pt.y *= MAZETEXTURE_HEIGHT;
  769. pSprite->MoveTo(pt);
  770. nSpecialState = ST_DOOR;
  771. break;
  772. case ST_DOOR:
  773. InitLevel();
  774. }
  775. }
  776. }
  777. //初始化精灵,它负责创建猪精灵,兔精灵,羊精灵,敌人精灵,特殊精灵和子弹精灵。
  778. void InitSprites()
  779. {
  780. const int nHeight = SPRITE_HEIGHT;
  781. const int nWidth = SPRITE_WIDTH;
  782. POINT pt;
  783. RECT rcBounding;
  784. // ---------------- 猪精灵----------------- //
  785. g_PigSprite.CreateSprite(&g_pSpriteSurface, TYPE_PLAYER, nHeight,nWidth);
  786. pt.x = 5*64; pt.y =7*64 ;
  787. g_PigSprite.AddState(ST_STAND_STILL, pt, 2, 60);
  788. rcBounding.top = 0;
  789. rcBounding.bottom = nHeight-10;
  790. rcBounding.left = 10;
  791. rcBounding.right= nWidth - 20;
  792. pt.x = 6*64; pt.y =4*64;
  793. g_PigSprite.AddState(ST_WALK_UP, pt, 3, 10,&rcBounding);
  794. rcBounding.top = 10;
  795. rcBounding.bottom = nHeight-10;
  796. pt.x = 64*9;pt.y = 4*64;
  797. g_PigSprite.AddState(ST_WALK_DOWN, pt, 3, 10,&rcBounding);
  798. rcBounding.top = 10;
  799. rcBounding.bottom = nHeight - 20;
  800. rcBounding.left = 0;
  801. rcBounding.right=nWidth - 10;
  802. pt.x = 3*64;pt.y = 4*64;
  803. // g_pPlayerSprite->AddState(ST_WALK_LEFT, pt, 2, 20,"WavPigWalk",true);
  804. g_PigSprite.AddState(ST_WALK_LEFT, pt, 3, 10,&rcBounding);
  805. pt.x = 64*0;pt.y = 4*64;
  806. rcBounding.left = 10;
  807. rcBounding.right=nWidth-10;
  808. g_PigSprite.AddState(ST_WALK_RIGHT, pt, 3, 10,&rcBounding);
  809. pt.x = 64 * 8; pt.y = 7 * 64;
  810. g_PigSprite.AddState(ST_KILL, pt, 4, 20);
  811. g_PigSprite.MoveTo(1 * MAZETEXTURE_WIDTH, 19 * MAZETEXTURE_HEIGHT);
  812. g_PigSprite.m_pfnDead = DeadPig;
  813. g_PigSprite.m_Movement.m_pfnCollision = IsHit;
  814. g_PigPooSprite.CreateSprite(&g_pSpriteSurface, TYPE_POO, nHeight,nWidth);
  815. rcBounding.top = rcBounding.left = 20;
  816. rcBounding.right=rcBounding.bottom = nHeight - 40;
  817. pt.x = 0*64;pt.y = 7*64;
  818. g_PigPooSprite.AddState(ST_DEFAULT, pt, 3, 50,&rcBounding);
  819. pt.x = 11*64;pt.y = 10*64;
  820. g_PigPooSprite.AddState(ST_DEAD, pt, 3, 50,&rcBounding);
  821. g_PigPooSprite.SetState(ST_DEFAULT);
  822. // --------------- 兔精灵 --------------- //
  823. g_RabbitSprite.CreateSprite(&g_pSpriteSurface, TYPE_PLAYER, nHeight,nWidth);
  824. pt.x = 5*64; pt.y =8*64 ;
  825. g_RabbitSprite.AddState(ST_STAND_STILL, pt, 2, 60);
  826. rcBounding.top = 0;
  827. rcBounding.bottom = nHeight-10;
  828. rcBounding.left = 10;
  829. rcBounding.right= nWidth - 20;
  830. pt.x = 6*64; pt.y =5*64;
  831. g_RabbitSprite.AddState(ST_WALK_UP, pt, 3, 10,&rcBounding);
  832. rcBounding.top = 10;
  833. rcBounding.bottom = nHeight-10;
  834. pt.x = 64*9;pt.y = 5*64;
  835. g_RabbitSprite.AddState(ST_WALK_DOWN, pt, 3, 10,&rcBounding);
  836. rcBounding.top = 10;
  837. rcBounding.bottom = nHeight - 20;
  838. rcBounding.left = 0;
  839. rcBounding.right=nWidth - 10;
  840. pt.x = 3*64;pt.y = 5*64;
  841. g_RabbitSprite.AddState(ST_WALK_LEFT, pt, 3, 10,&rcBounding);
  842. pt.x = 64*0;pt.y = 5*64;
  843. rcBounding.left = 10;
  844. rcBounding.right=nWidth-10;
  845. g_RabbitSprite.AddState(ST_WALK_RIGHT, pt, 3, 10,&rcBounding);
  846. pt.x = 64 * 8; pt.y = 8 * 64;
  847. g_RabbitSprite.AddState(ST_KILL, pt, 4, 20);
  848. g_RabbitSprite.MoveTo(1 * MAZETEXTURE_WIDTH, 19 * MAZETEXTURE_HEIGHT);
  849. g_RabbitSprite.m_pfnDead = DeadPig;
  850. g_RabbitSprite.m_Movement.m_pfnCollision = IsHit;
  851. g_RabbitPooSprite.CreateSprite(&g_pSpriteSurface, TYPE_POO, nHeight,nWidth);
  852. rcBounding.top = rcBounding.left = 20;
  853. rcBounding.right=rcBounding.bottom = nHeight - 40;
  854. pt.x = 0*64;pt.y = 8*64;
  855. g_RabbitPooSprite.AddState(ST_DEFAULT, pt, 3, 50,&rcBounding);
  856. pt.x = 11*64;pt.y = 10*64;
  857. g_RabbitPooSprite.AddState(ST_DEAD, pt, 3, 50,&rcBounding);
  858. g_RabbitPooSprite.SetState(ST_DEFAULT);
  859. // --------------- 羊精灵----------------//
  860. g_SheepSprite.CreateSprite(&g_pSpriteSurface, TYPE_PLAYER, nHeight,nWidth);
  861. pt.x = 5*64; pt.y =9*64 ;
  862. g_SheepSprite.AddState(ST_STAND_STILL, pt, 2, 60);
  863. rcBounding.top = 0;
  864. rcBounding.bottom = nHeight-10;
  865. rcBounding.left = 10;
  866. rcBounding.right= nWidth - 20;
  867. pt.x = 6*64; pt.y =6*64;
  868. g_SheepSprite.AddState(ST_WALK_UP, pt, 3, 10,&rcBounding);
  869. rcBounding.top = 10;
  870. rcBounding.bottom = nHeight-10;
  871. pt.x = 64*9;pt.y = 6*64;
  872. g_SheepSprite.AddState(ST_WALK_DOWN, pt, 3, 10,&rcBounding);
  873. rcBounding.top = 10;
  874. rcBounding.bottom = nHeight - 20;
  875. rcBounding.left = 0;
  876. rcBounding.right=nWidth - 10;
  877. pt.x = 3*64;pt.y = 6*64;
  878. g_SheepSprite.AddState(ST_WALK_LEFT, pt, 3, 10,&rcBounding);
  879. pt.x = 64*0;pt.y = 6*64;
  880. rcBounding.left = 10;
  881. rcBounding.right=nWidth-10;
  882. g_SheepSprite.AddState(ST_WALK_RIGHT, pt, 3, 10,&rcBounding);
  883. pt.x = 64 * 8; pt.y = 9 * 64;
  884. g_SheepSprite.AddState(ST_KILL, pt, 4, 20);
  885. g_SheepSprite.MoveTo(1 * MAZETEXTURE_WIDTH, 19 * MAZETEXTURE_HEIGHT);
  886. g_SheepSprite.m_pfnDead = DeadPig;
  887. g_SheepSprite.m_Movement.m_pfnCollision = IsHit;
  888. g_SheepPooSprite.CreateSprite(&g_pSpriteSurface, TYPE_POO, nHeight,nWidth);
  889. rcBounding.top = rcBounding.left = 20;
  890. rcBounding.right=rcBounding.bottom = nHeight - 40;
  891. pt.x = 0*64;pt.y = 9*64;
  892. g_SheepPooSprite.AddState(ST_DEFAULT, pt, 3, 50,&rcBounding);
  893. pt.x = 11*64;pt.y = 10*64;
  894. g_SheepPooSprite.AddState(ST_DEAD, pt, 3, 50,&rcBounding);
  895. g_SheepPooSprite.SetState(ST_DEFAULT);
  896. // --------------- 敌人精灵--------------------//
  897. //敌人精灵管理器
  898. g_EnemySpriteManager.SetCollAndPathFn(IsHit, FindPath);
  899. rcBounding.left =  10;
  900. rcBounding.top =0;
  901. rcBounding.right = SPRITE_WIDTH - 20;
  902. rcBounding.bottom = SPRITE_HEIGHT ;
  903.     g_Enemy1Sprite.CreateSprite(&g_pSpriteSurface, TYPE_ENEMY1, nHeight,nWidth);
  904. pt.x = 6*64;pt.y = 0*64;
  905. g_Enemy1Sprite.AddState(ST_WALK_UP, pt, 2, 20,&rcBounding);
  906. pt.x = 3*64;pt.y = 0*64;
  907. g_Enemy1Sprite.AddState(ST_WALK_LEFT, pt, 3, 20,&rcBounding);
  908. pt.x = 0*64;pt.y = 0*64;
  909. g_Enemy1Sprite.AddState(ST_WALK_RIGHT, pt, 3, 20,&rcBounding);
  910. pt.x = 8*64;pt.y = 0*64;
  911. g_Enemy1Sprite.AddState(ST_WALK_DOWN, pt, 2, 20,&rcBounding);
  912. pt.x = 10*64;pt.y = 0*64;
  913. g_Enemy1Sprite.AddState(ST_KILL, pt, 3, 100);
  914. g_Enemy1Sprite.m_pfnDead= DeadEnemy;
  915. g_Enemy1Sprite.m_nPoints = 100;
  916.     g_Enemy2Sprite.CreateSprite(&g_pSpriteSurface, TYPE_ENEMY2, nHeight,nWidth);
  917. pt.x = 6*64;pt.y = 1*64;
  918. g_Enemy2Sprite.AddState(ST_WALK_UP, pt, 2, 20,&rcBounding);
  919. pt.x = 3*64;pt.y = 1*64;
  920. g_Enemy2Sprite.AddState(ST_WALK_LEFT, pt, 3, 20,&rcBounding);
  921. pt.x = 0*64;pt.y = 1*64;
  922. g_Enemy2Sprite.AddState(ST_WALK_RIGHT, pt, 3, 20,&rcBounding);
  923. pt.x = 8*64;pt.y = 1*64;
  924. g_Enemy2Sprite.AddState(ST_WALK_DOWN, pt, 2, 20,&rcBounding);
  925. pt.x = 10*64;pt.y = 1*64;
  926. g_Enemy2Sprite.AddState(ST_KILL, pt, 3, 100);
  927. g_Enemy2Sprite.m_pfnDead= DeadEnemy;
  928. g_Enemy2Sprite.m_nPoints = 100;
  929.     g_Enemy3Sprite.CreateSprite(&g_pSpriteSurface, TYPE_ENEMY3, nHeight,nWidth);
  930. pt.x = 6*64;pt.y = 2*64;
  931. g_Enemy3Sprite.AddState(ST_WALK_UP, pt, 2, 20,&rcBounding);
  932. pt.x = 3*64;pt.y = 2*64;
  933. g_Enemy3Sprite.AddState(ST_WALK_LEFT, pt, 3, 20,&rcBounding);
  934. pt.x = 0*64;pt.y = 2*64;
  935. g_Enemy3Sprite.AddState(ST_WALK_RIGHT, pt, 3, 20,&rcBounding);
  936. pt.x = 8*64;pt.y = 2*64;
  937. g_Enemy3Sprite.AddState(ST_WALK_DOWN, pt, 2, 20,&rcBounding);
  938. pt.x = 10*64;pt.y = 2*64;
  939. g_Enemy3Sprite.AddState(ST_KILL, pt, 3, 100);
  940. g_Enemy3Sprite.m_pfnDead= DeadEnemy;
  941. g_Enemy3Sprite.m_nPoints = 100;
  942. g_EnemySpriteManager.AddSprite(&g_Enemy3Sprite);
  943.     g_Enemy4Sprite.CreateSprite(&g_pSpriteSurface, TYPE_ENEMY4, nHeight,nWidth);
  944. pt.x = 6*64;pt.y = 3*64;
  945. g_Enemy4Sprite.AddState(ST_WALK_UP, pt, 2, 20,&rcBounding);
  946. pt.x = 3*64;pt.y = 3*64;
  947. g_Enemy4Sprite.AddState(ST_WALK_LEFT, pt, 3, 20,&rcBounding);
  948. pt.x = 0*64;pt.y = 3*64;
  949. g_Enemy4Sprite.AddState(ST_WALK_RIGHT, pt, 3, 20,&rcBounding);
  950. pt.x = 8*64;pt.y = 3*64;
  951. g_Enemy4Sprite.AddState(ST_WALK_DOWN, pt, 2, 20,&rcBounding);
  952. pt.x = 10*64;pt.y =3*64;
  953. g_Enemy4Sprite.AddState(ST_KILL, pt, 3, 100);
  954. g_Enemy4Sprite.m_pfnDead= DeadEnemy;
  955. g_Enemy4Sprite.m_nPoints = 200;
  956. g_EnemySpriteManager.AddSprite(&g_Enemy4Sprite);
  957.     g_Enemy5Sprite.CreateSprite(&g_pSpriteSurface, TYPE_ENEMY4, nHeight,nWidth);
  958. pt.x = 6*64;pt.y = 3*64;
  959. g_Enemy5Sprite.AddState(ST_WALK_UP, pt, 2, 20,&rcBounding);
  960. pt.x = 3*64;pt.y = 3*64;
  961. g_Enemy5Sprite.AddState(ST_WALK_LEFT, pt, 3, 20,&rcBounding);
  962. pt.x = 0*64;pt.y = 3*64;
  963. g_Enemy5Sprite.AddState(ST_WALK_RIGHT, pt, 3, 20,&rcBounding);
  964. pt.x = 8*64;pt.y = 3*64;
  965. g_Enemy5Sprite.AddState(ST_WALK_DOWN, pt, 2, 20,&rcBounding);
  966. pt.x = 10*64;pt.y =3*64;
  967. g_Enemy5Sprite.AddState(ST_KILL, pt, 3, 100);
  968. g_Enemy5Sprite.m_pfnDead= DeadEnemy;
  969. g_Enemy5Sprite.m_nPoints = 200;
  970. g_EnemySpriteManager.AddSprite(&g_Enemy5Sprite);
  971. //其它精灵
  972. g_SpecialSprite.CreateSprite(&g_pSpriteSurface, TYPE_SPECIAL, nHeight,nWidth);
  973. pt.x = 5*64;pt.y = 10*64;
  974. g_SpecialSprite.AddState(ST_FOOD1, pt, 1, 100);
  975. pt.x = 6*64;pt.y = 10*64;
  976. g_SpecialSprite.AddState(ST_FOOD2, pt, 1, 100);
  977. pt.x = 7*64;pt.y = 10*64;
  978. g_SpecialSprite.AddState(ST_FOOD3, pt, 1, 100);
  979. pt.x = 8*64;pt.y = 10*64;
  980. g_SpecialSprite.AddState(ST_FOOD4, pt, 1, 100);
  981. pt.x = 9*64;pt.y = 10*64;
  982. g_SpecialSprite.AddState(ST_FOOD5, pt, 1, 100);
  983. pt.x = 10*64;pt.y = 10*64;
  984. g_SpecialSprite.AddState(ST_FOOD6, pt, 1, 100);
  985. pt.x = 3*64;pt.y = 8*64;
  986. g_SpecialSprite.AddState(ST_KEY, pt, 2, 50);
  987. pt.x = 2*64;pt.y = 10*64;
  988. g_SpecialSprite.AddState(ST_DOOR, pt, 3, 30);
  989. pt.x = 3*64;pt.y = 7*64;
  990. g_SpecialSprite.AddState(ST_KILL, pt, 2, 100);
  991. g_SpecialSprite.m_nPoints = 200;
  992. g_SpecialSprite.m_pfnDead = DeadSpecial;
  993. g_SpecialSprite.m_pfnKill = KillSpecial;
  994. // ----------子弹精灵------------  //
  995. g_BulletSprite.CreateSprite(&g_pSpriteSurface, TYPE_BULLET, nHeight,nWidth);
  996. rcBounding.top = rcBounding.left = 20;
  997. rcBounding.right=rcBounding.bottom = nHeight - 40;
  998. pt.x = 0*64;pt.y = 10*64;
  999. g_BulletSprite.AddState(ST_DEFAULT, pt, 2, 30, &rcBounding);
  1000. pt.x = 11*64;pt.y = 10*64;
  1001. g_BulletSprite.AddState(ST_KILL, pt, 1, 10);
  1002. g_BulletSprite.m_Movement.m_pfnCollision = IsHit;
  1003. g_BulletSprite.m_Movement.m_nPathFindDelay = 5000;
  1004. g_BulletSprite.m_Movement.m_pfnFindPath=BulletFindPath;
  1005. g_BulletSprite.SetState(ST_KILL);
  1006. /*
  1007. g_Enemy1Sprite.EnableBorder(true);
  1008. g_Enemy2Sprite.EnableBorder(true);
  1009. g_Enemy3Sprite.EnableBorder(true);
  1010. g_PigSprite.EnableBorder(true);
  1011. g_RabbitSprite.EnableBorder(true);
  1012. g_SheepSprite.EnableBorder(true);
  1013. g_BulletSprite.EnableBorder(true);
  1014. */
  1015. }
  1016. void InitLevel()
  1017. {
  1018. if (g_nCurrLevel+1 > g_nNoOfLevels) {
  1019. g_nGameState = GAMESTATE_GAMEOVERGOOD;
  1020. LoadJPEG(true, GAMEOVERGOODFILENAME,  &g_pSplashSurface);
  1021. return;
  1022. }
  1023. int nNoOfEnemies = g_pLevel[g_nCurrLevel].nNoOfEnemys;
  1024. g_Maze.LoadMaze(g_pLevel[g_nCurrLevel++].szLevelFile);
  1025. g_nNoOfEnemies = 10;
  1026. SAFE_DELETE( g_pScoreTextSurface );
  1027. wsprintf((char*)g_szScore, (char*)GAMESCORE_TEXT, g_nScore);
  1028. HFONT hFont = GetGameFont();
  1029.     g_pDisplay->CreateSurfaceFromText( &g_pScoreTextSurface, hFont, (char*)g_szScore, 
  1030. RGB(0,0,0), RGB(255, 255, 0) );
  1031. /*
  1032. OutputDebugString("n-----------n");
  1033. char szDebug[100];
  1034. wsprintf (szDebug,"g_nRows %d, g_nCols :%d Sizeof %dn",g_nRows,g_nCols,sizeof(short[g_nCols][g_nRows]));
  1035. OutputDebugString(szDebug);
  1036. for (int i=0; i < g_nRows; i++) {
  1037. for(int j=0; j <g_nCols; j++) {
  1038. if (g_nPathArray[i][j] !=0) 
  1039. szDebug[j]='1';
  1040. else
  1041. szDebug[j]='0';
  1042. }
  1043. szDebug[j]='n';
  1044. szDebug[j+1]='';
  1045. OutputDebugString(szDebug);
  1046. }
  1047. OutputDebugString("-----------n");
  1048. */
  1049.     g_nNoOfSpecials = NO_OF_SPECIALS;
  1050. SAFE_DELETE(g_pLevelTextSurface);
  1051.     g_pDisplay->CreateSurfaceFromText( &g_pLevelTextSurface, hFont, g_Maze.GetName(), 
  1052. RGB(0,0,0), RGB(255, 255, 0) ) ;
  1053. POINT pt= { 0*64, 3*64 };
  1054. g_pPlayerSprite->MoveTo(1 * MAZETEXTURE_WIDTH, 19 * MAZETEXTURE_HEIGHT);
  1055.     g_pPlayerSprite->SetState(ST_WALK_UP, true);
  1056. g_pPlayerSprite->m_Movement.m_dx=0;
  1057. g_pPlayerSprite->m_Movement.m_dy=0;
  1058. g_pPlayerSprite->m_Movement.m_nInvulnerable=INVULNERABLE_DELAY;
  1059. g_pPooSprite->SetState(ST_DEAD, true);
  1060. g_EnemySpriteManager.Destroy();
  1061. if (nNoOfEnemies) {
  1062. nNoOfEnemies--;
  1063. pt= g_Maze.GetRandDeployPoint();
  1064. pt.x *= MAZETEXTURE_WIDTH;
  1065. pt.y *= MAZETEXTURE_HEIGHT;
  1066. g_Enemy1Sprite.MoveTo(pt);
  1067. g_Enemy1Sprite.m_Movement.m_dx = -1;
  1068. g_Enemy1Sprite.m_Movement.m_nPathFindDelay = 1000;
  1069. g_Enemy1Sprite.SetState(ST_WALK_LEFT, true);
  1070. g_EnemySpriteManager.AddSprite(&g_Enemy1Sprite);
  1071. }
  1072. if (nNoOfEnemies) {
  1073. nNoOfEnemies--;
  1074. pt= g_Maze.GetRandDeployPoint();
  1075. pt.x *= MAZETEXTURE_WIDTH;
  1076. pt.y *= MAZETEXTURE_HEIGHT;
  1077. g_Enemy2Sprite.MoveTo(pt);
  1078. g_Enemy2Sprite.m_Movement.m_dx = 1;
  1079. g_Enemy2Sprite.m_Movement.m_nPathFindDelay = 500;
  1080. g_Enemy2Sprite.SetState(ST_WALK_RIGHT, true);
  1081. g_EnemySpriteManager.AddSprite(&g_Enemy2Sprite);
  1082. }
  1083. if (nNoOfEnemies) {
  1084. nNoOfEnemies--;
  1085. pt= g_Maze.GetRandDeployPoint();
  1086. pt.x *= MAZETEXTURE_WIDTH;
  1087. pt.y *= MAZETEXTURE_HEIGHT;
  1088. g_Enemy3Sprite.MoveTo(pt);
  1089. g_Enemy3Sprite.m_Movement.m_dy = 1;
  1090. g_Enemy3Sprite.m_Movement.m_nPathFindDelay = 300;
  1091. g_Enemy3Sprite.SetState(ST_WALK_DOWN, true);
  1092. g_EnemySpriteManager.AddSprite(&g_Enemy3Sprite);
  1093. }
  1094. if (nNoOfEnemies) {
  1095. nNoOfEnemies--;
  1096. pt= g_Maze.GetRandDeployPoint();
  1097. pt.x *= MAZETEXTURE_WIDTH;
  1098. pt.y *= MAZETEXTURE_HEIGHT;
  1099. g_Enemy4Sprite.MoveTo(pt);
  1100. g_Enemy4Sprite.m_Movement.m_dy = -1;
  1101. g_Enemy4Sprite.m_Movement.m_nPathFindDelay = 200;
  1102. g_Enemy4Sprite.SetState(ST_WALK_UP, true);
  1103. g_EnemySpriteManager.AddSprite(&g_Enemy4Sprite);
  1104. }
  1105. if (nNoOfEnemies) {
  1106. nNoOfEnemies--;
  1107. pt= g_Maze.GetRandDeployPoint();
  1108. pt.x *= MAZETEXTURE_WIDTH;
  1109. pt.y *= MAZETEXTURE_HEIGHT;
  1110. g_Enemy5Sprite.MoveTo(pt);
  1111. g_Enemy5Sprite.m_Movement.m_dy = 1;
  1112. g_Enemy5Sprite.m_Movement.m_nPathFindDelay = 200;
  1113. g_Enemy5Sprite.SetState(ST_WALK_DOWN, true);
  1114. g_EnemySpriteManager.AddSprite(&g_Enemy5Sprite);
  1115. }
  1116. pt= g_Maze.GetRandDeployPoint();
  1117. pt.x *= MAZETEXTURE_WIDTH;
  1118. pt.y *= MAZETEXTURE_HEIGHT;
  1119. g_SpecialSprite.MoveTo(pt);
  1120. g_SpecialSprite.SetState(ST_FOOD1, true);
  1121. // SIZE szDim = { 64,64};
  1122. // g_Maze.DisplayGrid(true);
  1123. // g_Maze.DisplayDeployRects(szDim);
  1124. g_Maze.Draw(g_pMazeSurface);
  1125. SAFE_DELETE( g_pLifeTextSurface );
  1126. wsprintf((char*)g_szLifeLeft, (char*)LIFE_LEFT_TEXT, g_nLivesLeft - 1);
  1127.     g_pDisplay->CreateSurfaceFromText( &g_pLifeTextSurface, hFont, (char*)g_szLifeLeft, 
  1128. RGB(0,0,0), RGB(255, 255, 0) );
  1129. DeleteObject(hFont);
  1130. }
  1131. //-----------------------------------------------------------------------------
  1132. // Name: FreeDirectDraw()
  1133. // Desc: Release all the DirectDraw objects
  1134. //-----------------------------------------------------------------------------
  1135. VOID FreeDirectDraw()
  1136. {
  1137. #ifdef DISPLAY_STATUS
  1138.     SAFE_DELETE( g_pTextSurface );
  1139. #endif
  1140. SAFE_DELETE( g_pLifeTextSurface );
  1141. SAFE_DELETE( g_pScoreTextSurface );
  1142. SAFE_DELETE( g_pLevelTextSurface );
  1143.     SAFE_DELETE( g_pMazeSurface );
  1144. SAFE_DELETE( g_pSpriteSurface );
  1145. SAFE_DELETE( g_pSplashSurface);
  1146.     SAFE_DELETE( g_pDisplay );
  1147. SAFE_DELETE( g_pSplashSound );
  1148. SAFE_DELETE( g_pPickupSound );
  1149.     SAFE_DELETE( g_pSoundManager );
  1150. SAFE_DELETE( g_pHandleInput );
  1151. }
  1152. //-----------------------------------------------------------------------------
  1153. // Name: MainWndProc()
  1154. // Desc: The main window procedure
  1155. //-----------------------------------------------------------------------------
  1156. LRESULT CALLBACK MainWndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
  1157. {
  1158.     switch (msg)
  1159.     {
  1160. case WM_COMMAND:
  1161. switch( LOWORD(wParam) )
  1162. {
  1163. case IDM_TOGGLEFULLSCREEN: //Alt+回车快捷键的消息处理函数
  1164. //这个快捷键用来切换满屏/窗口模式,这是满屏程序常用的快捷键
  1165. if( g_bWindowed )
  1166. GetWindowRect( hWnd, &g_rcWindow );
  1167. g_bWindowed = !g_bWindowed;
  1168. //初始化绘制模式
  1169. if( FAILED( InitDirectDrawMode( hWnd, g_bWindowed ) ) )
  1170. {
  1171. SAFE_DELETE( g_pDisplay );
  1172. MessageBox( hWnd, TEXT("InitDirectDraw() failed. ")
  1173. TEXT("The sample will now exit. "), TEXT("DirectDraw Sample"), 
  1174. MB_ICONERROR | MB_OK );
  1175. PostMessage( hWnd, WM_CLOSE, 0, 0 );
  1176. }
  1177. return 0L;
  1178. case IDM_PAUSE: //Pause快捷键的消息处理函数
  1179. g_bActive = true - g_bActive;
  1180. return 0L;
  1181. case IDM_EXIT: //Esc快捷键的消息处理函数
  1182. PostMessage( hWnd, WM_CLOSE, 0, 0 );
  1183. return 0L;
  1184. }
  1185. break; // Continue with default processing
  1186.         case WM_GETMINMAXINFO: //窗口模式下的消息
  1187.             {
  1188. //不允许改变窗口大小,固定窗口尺寸
  1189.                 MINMAXINFO* pMinMax = (MINMAXINFO*) lParam;
  1190.                 DWORD dwFrameWidth    = GetSystemMetrics( SM_CXSIZEFRAME );
  1191.                 DWORD dwFrameHeight   = GetSystemMetrics( SM_CYSIZEFRAME );
  1192.                 DWORD dwMenuHeight    = GetSystemMetrics( SM_CYMENU );
  1193.                 DWORD dwCaptionHeight = GetSystemMetrics( SM_CYCAPTION );
  1194.                 pMinMax->ptMinTrackSize.x = SCREEN_WIDTH  + dwFrameWidth * 2;
  1195.                 pMinMax->ptMinTrackSize.y = SCREEN_HEIGHT + dwFrameHeight * 2 + 
  1196. dwMenuHeight + dwCaptionHeight;
  1197.                 pMinMax->ptMaxTrackSize.x = pMinMax->ptMinTrackSize.x;
  1198.                 pMinMax->ptMaxTrackSize.y = pMinMax->ptMinTrackSize.y;
  1199.             }
  1200.             return 0L;
  1201.         case WM_MOVE: //窗口模式下的消息
  1202. //移动窗口
  1203.             if( g_pDisplay )
  1204.                 g_pDisplay->UpdateBounds();
  1205.             return 0L;
  1206.         case WM_SIZE: //检测游戏是否失去了窗口焦点
  1207.             if( SIZE_MAXHIDE==wParam || SIZE_MINIMIZED==wParam )
  1208.                 g_bActive = FALSE;
  1209.             else
  1210.                 g_bActive = TRUE;
  1211.             if( g_pDisplay )
  1212.                 g_pDisplay->UpdateBounds();
  1213.             break;
  1214.         case WM_SETCURSOR: //光标消息
  1215.             // 在全屏模式下隐藏光标
  1216.             if( !g_bWindowed )
  1217.             {
  1218.                 SetCursor( NULL );
  1219.                 return TRUE;
  1220.             }
  1221.             break; 
  1222.         case WM_QUERYNEWPALETTE: //
  1223.             if( g_pDisplay && g_pDisplay->GetFrontBuffer() )            
  1224.             {
  1225.                 // If we are in windowed mode with a desktop resolution in 8 bit 
  1226.                 // color, then the palette we created during init has changed 
  1227.                 // since then.  So get the palette back from the primary 
  1228.                 // DirectDraw surface, and set it again so that DirectDraw 
  1229.                 // realises the palette, then release it again. 
  1230.                 LPDIRECTDRAWPALETTE pDDPal = NULL; 
  1231.                 g_pDisplay->GetFrontBuffer()->GetPalette( &pDDPal );
  1232.                 g_pDisplay->GetFrontBuffer()->SetPalette( pDDPal );
  1233.                 SAFE_RELEASE( pDDPal );
  1234.             }
  1235.             break;
  1236.         case WM_EXITMENULOOP: //忽略在菜单上花费的时间
  1237.             g_dwLastTick = timeGetTime();
  1238.             break;
  1239.         case WM_EXITSIZEMOVE: //忽略移动窗口的时间
  1240.             g_dwLastTick = timeGetTime();
  1241.             break;
  1242. case WM_SYSCOMMAND: //防止全屏模式下的移动/变尺和调电
  1243.             switch( wParam )
  1244.             {
  1245. case SC_MOVE:
  1246. case SC_SIZE:
  1247. case SC_MAXIMIZE:
  1248. case SC_MONITORPOWER:
  1249. if( !g_bWindowed )
  1250. return TRUE;
  1251.             }
  1252.             break;
  1253. case WM_DESTROY: //清除,结束游戏
  1254. FreeDirectDraw();
  1255. PostQuitMessage( 0 );
  1256. return 0L;
  1257. break;
  1258.     }
  1259.     return DefWindowProc(hWnd, msg, wParam, lParam);
  1260. }
  1261. //-----------------------------------------------------------------------------
  1262. // Name: ProcessNextFrame()
  1263. // Desc: Move the sprites, blt them to the back buffer, then 
  1264. //       flip or blt the back buffer to the primary buffer
  1265. //-----------------------------------------------------------------------------
  1266. HRESULT ProcessNextFrame( HWND hWnd )
  1267. {
  1268.     HRESULT hr;
  1269.     // Figure how much time has passed since the last time
  1270.     DWORD dwCurrTick = timeGetTime();
  1271.     DWORD dwTickDiff = dwCurrTick - g_dwLastTick;
  1272.     // Don't update if no time has passed 
  1273.     if( dwTickDiff == 0 )
  1274. return S_OK; 
  1275. g_dwLastTick = dwCurrTick;
  1276. dwTickDiff = 17 - dwTickDiff;
  1277.   if (dwTickDiff > 0 && dwTickDiff < 17)
  1278.   Sleep(dwTickDiff);
  1279. // Sleep(10);
  1280.     // Check the cooperative level before rendering
  1281.     if( FAILED( hr = g_pDisplay->GetDirectDraw()->TestCooperativeLevel() ) )
  1282.     {
  1283.         switch( hr )
  1284.         {
  1285. case DDERR_EXCLUSIVEMODEALREADYSET:
  1286. case DDERR_NOEXCLUSIVEMODE:
  1287. // Do nothing because some other app has exclusive mode
  1288. Sleep(10);
  1289. return S_OK;
  1290. case DDERR_WRONGMODE:
  1291. // The display mode changed on us. Update the
  1292. // DirectDraw surfaces accordingly
  1293. return InitDirectDrawMode( hWnd, g_bWindowed );
  1294.         }
  1295.         return hr;
  1296.     }
  1297.     // Display the sprites on the screen
  1298.     if( FAILED( hr = DisplayFrame() ) )
  1299.     {
  1300.         if( hr != DDERR_SURFACELOST )
  1301.             return hr;
  1302.         // The surfaces were lost so restore them 
  1303.         RestoreSurfaces();
  1304.     }
  1305.     return S_OK;
  1306. }
  1307. //-----------------------------------------------------------------------------
  1308. // Name: DisplayFrame()
  1309. // Desc: Blts a the sprites to the back buffer, then it blts or flips the 
  1310. //       back buffer onto the primary buffer.
  1311. //-----------------------------------------------------------------------------
  1312. HRESULT DisplayFrame()
  1313. {
  1314.     HRESULT hr;
  1315. if( Input() )
  1316. Input()->UpdateDevices();
  1317.     // Fill the back buffer with black, ignoring errors until the flip
  1318.     g_pDisplay->Clear( 0 );
  1319. switch (g_nGameState)
  1320. {
  1321. case GAMESTATE_SPLASHSCREEN:
  1322. {
  1323. if (g_pSplashSound == NULL) {
  1324. g_pSoundManager->Create( &g_pSplashSound, "WavSplashScreen", 0, GUID_NULL );
  1325. }
  1326. if (g_pSplashSound->IsSoundPlaying() == false) {
  1327. g_pSplashSound->Play(0,DSBPLAY_LOOPING);
  1328. LoadJPEG(true, SPLASHFILENAME,  &g_pSplashSurface);
  1329. }
  1330. g_pDisplay->Blt(0,0, g_pSplashSurface, NULL);
  1331. break;
  1332. }
  1333. case GAMESTATE_CHOICE:
  1334. {
  1335. g_pDisplay->Blt(0,0, g_pSplashSurface, NULL);
  1336. break;
  1337. }
  1338. case GAMESTATE_RUNNING:
  1339. {
  1340. LPDIRECTDRAWSURFACE7 lpdds = g_pDisplay->GetBackBuffer();
  1341. if (g_nPooDelay)
  1342. --g_nPooDelay;
  1343. else {
  1344. g_pPooSprite->SetState(ST_DEAD);
  1345. }
  1346. g_pDisplay->Blt( 0, 0, g_pMazeSurface, NULL );
  1347. // Blt the help text on the backbuffer, ignoring errors until the flip
  1348. #ifdef DISPLAY_STATUS
  1349. g_pDisplay->Blt( 10, 10, g_pTextSurface, NULL );
  1350. #endif
  1351. g_pDisplay->Blt( 10, 710, g_pLifeTextSurface, NULL );
  1352. g_pDisplay->Blt( SCREEN_WIDTH - g_pScoreTextSurface->GetSurfaceDesc().dwWidth - 10, 710, g_pScoreTextSurface, NULL );
  1353. g_pDisplay->Blt( SCREEN_WIDTH/2 - g_pLevelTextSurface->GetSurfaceDesc().dwWidth/2, 710, g_pLevelTextSurface, NULL );
  1354. g_pPooSprite->Update();
  1355. g_pPlayerSprite->Update();
  1356. g_SpecialSprite.Update();
  1357. g_EnemySpriteManager.Update();
  1358. g_BulletSprite.Update();
  1359. g_EnemySpriteManager.KillSpritesColliWith(g_pPooSprite);
  1360. if (g_pPlayerSprite->m_Movement.m_nInvulnerable == 0) {
  1361. if (g_EnemySpriteManager.IsHit(g_pPlayerSprite->GetRect()) || g_BulletSprite.IsHit(g_pPlayerSprite->GetRect())) {
  1362. g_pPlayerSprite->SetState(ST_KILL);
  1363. g_BulletSprite.SetState(ST_KILL);
  1364. g_pPlayerSprite->m_Movement.m_dx = g_pPlayerSprite->m_Movement.m_dy =0;
  1365. }
  1366. }
  1367. if (g_SpecialSprite.IsHit(g_pPlayerSprite->GetRect()) && g_SpecialSprite.GetState()!=ST_KILL) {
  1368. g_pPickupSound->Play(0,0);
  1369. g_SpecialSprite.SetState(ST_KILL);
  1370. }
  1371. g_pPooSprite->Draw(lpdds);
  1372. g_SpecialSprite.Draw(lpdds);
  1373. g_pPlayerSprite->Draw(lpdds);
  1374. g_BulletSprite.Draw(lpdds);
  1375. g_EnemySpriteManager.Draw(lpdds);
  1376. break;
  1377. }
  1378. case GAMESTATE_GAMEOVERGOOD:
  1379. case GAMESTATE_GAMEOVERBAD:
  1380. {
  1381. g_pDisplay->Blt(0,0, g_pSplashSurface, NULL);
  1382. }
  1383. }
  1384. // Flip or blt the back buffer onto the primary buffer
  1385. if( FAILED( hr = g_pDisplay->Present() ) )
  1386. return hr;
  1387. return S_OK;
  1388. }
  1389. //-----------------------------------------------------------------------------
  1390. // Name: RestoreSurfaces()
  1391. // Desc: Restore all the surfaces, and redraw the sprite surfaces.
  1392. //-----------------------------------------------------------------------------
  1393. HRESULT RestoreSurfaces()
  1394. {
  1395.     HRESULT hr;
  1396.     LPDIRECTDRAWPALETTE  pDDPal = NULL; 
  1397.     if( FAILED( hr = g_pDisplay->GetDirectDraw()->RestoreAllSurfaces() ) )
  1398.         return hr;
  1399. // No need to re-create the surface, just re-draw it.
  1400. #ifdef DISPLAY_STATUS
  1401. if( FAILED( hr = g_pTextSurface->DrawText( NULL, (char*)g_szGameStatus, 
  1402. 0, 0, RGB(0,0,0), RGB(255, 255, 0) ) ) )
  1403. return hr;
  1404. #endif
  1405. if( FAILED( hr = g_pLifeTextSurface->DrawText( NULL, (char*)g_szLifeLeft, 
  1406. 0, 0, RGB(0,0,0), RGB(255, 255, 0) ) ) )
  1407. return hr;
  1408. if( FAILED( hr = g_pScoreTextSurface->DrawText( NULL, (char*)g_szScore, 
  1409. 0, 0, RGB(0,0,0), RGB(255, 255, 0) ) ) )
  1410. return hr;
  1411. if( FAILED( hr = g_pLevelTextSurface->DrawText( NULL, g_Maze.GetName(), 
  1412. 0, 0, RGB(0,0,0), RGB(255, 255, 0) ) ) )
  1413. return hr;
  1414. g_Maze.Draw(g_pMazeSurface);
  1415. if( FAILED( hr = g_pSpriteSurface->DrawBitmap( "Sprite.bmp"/*MAKEINTRESOURCE( IDB_SPRITE )*/,
  1416. 0, 0 ) ) )
  1417.         return hr;
  1418. if (g_nGameState == GAMESTATE_SPLASHSCREEN) {
  1419. LoadJPEG(true, SPLASHFILENAME,  &g_pSplashSurface);
  1420. }
  1421. if (g_nGameState == GAMESTATE_CHOICE) {
  1422. LoadJPEG(true, CHOICEFILENAME,  &g_pSplashSurface);
  1423. }
  1424. if (g_nGameState == GAMESTATE_GAMEOVERGOOD) {
  1425. LoadJPEG(true, GAMEOVERGOODFILENAME,  &g_pSplashSurface);
  1426. }
  1427. if (g_nGameState == GAMESTATE_GAMEOVERBAD) {
  1428. LoadJPEG(true, GAMEOVERBADFILENAME,  &g_pSplashSurface);
  1429. }
  1430.     return S_OK;
  1431. }
  1432. //16Bit Color conversion macros
  1433. #define RGB555(r, g, b) ((r >> 3) | ((g >> 3) << 5) | ((b >> 3) << 10))
  1434. #define RGB565(r, g, b) ((r >> 3) | ((g >> 2) << 5) | ((b >> 3) << 11))
  1435. //16Bit Color Formats
  1436. #define PF_555  1
  1437. #define PF_565  2
  1438. //Color modes
  1439. #define C16BIT  16
  1440. #define C24BIT  24
  1441. #define C32BIT  32
  1442. //*************
  1443. //* Load JPEG *
  1444. //*************
  1445. bool LoadJPEG(bool bFromFile, LPCTSTR szName,  CSurface** ppSurface)
  1446. {
  1447. //Error handle
  1448. IJLERR jerr;
  1449. int  nPixelFormat = PF_555;
  1450. //Create the JPEG object
  1451. JPEG_CORE_PROPERTIES jcprops;
  1452. DDPIXELFORMAT DDPixelFormat;
  1453. ZeroMemory(&DDPixelFormat, sizeof(DDPixelFormat));
  1454. DDPixelFormat.dwSize = sizeof(DDPixelFormat);
  1455. HRESULT Result = g_pDisplay->GetBackBuffer()->GetPixelFormat(&DDPixelFormat);
  1456. if(Result != DD_OK)
  1457. {
  1458. MessageBox(g_hMainWnd, "Failed to retrieve pixel format", TITLE, MB_OK);
  1459. return false;
  1460. }
  1461. //Get green bitmask and set pixel format    
  1462. if((DDPixelFormat.dwGBitMask / 32) == 31)
  1463. nPixelFormat = PF_555;
  1464. else if((DDPixelFormat.dwGBitMask / 32) == 63)
  1465. nPixelFormat = PF_565;
  1466. //Initialize the JPEG object
  1467. jerr = ijlInit(&jcprops);
  1468. if (jerr != IJL_OK)
  1469. {
  1470. MessageBox(g_hMainWnd, "IJLInit problem", TITLE, MB_OK);
  1471. return false;
  1472. }
  1473. //Load from File or Resource?
  1474. if (bFromFile)
  1475. {
  1476. //Set the IJL data source as a filename
  1477. jcprops.JPGFile = szName;
  1478. //Read JPEG parameters from the file
  1479. jerr = ijlRead(&jcprops, IJL_JFILE_READPARAMS);
  1480. }
  1481. else //(Location == FROM_RESOURCE) or integer ID of resource
  1482. {
  1483. //Resource variables
  1484. BYTE* pmem;
  1485. HGLOBAL hmem;
  1486. DWORD size;
  1487. HRSRC hres;
  1488. hres = FindResource(NULL, szName, "JPEG");
  1489. if (hres)
  1490. {
  1491. size = SizeofResource(NULL, hres);
  1492. if (!size)
  1493. {
  1494. MessageBox(g_hMainWnd, "Error retrieving resource size",
  1495. TITLE, MB_OK);
  1496. return false;
  1497. }
  1498. hmem = LoadResource(NULL, hres);
  1499. if (hmem == NULL)
  1500. {
  1501. MessageBox(g_hMainWnd, "Error loading resource", TITLE, MB_OK);
  1502. return false;
  1503. }
  1504. pmem = (BYTE *)LockResource(hmem);
  1505. if (pmem == NULL)
  1506. {
  1507. MessageBox(g_hMainWnd, "Error locking resource", TITLE, MB_OK);
  1508. return false;
  1509. }
  1510. }
  1511. else
  1512. {
  1513. MessageBox(g_hMainWnd, "JPEG resource not found", TITLE, MB_OK);
  1514. return false;
  1515. }
  1516. //Set the IJL data source as the resource buffer
  1517. jcprops.JPGFile      = NULL;
  1518. jcprops.JPGBytes     = pmem;
  1519. jcprops.JPGSizeBytes = size;
  1520. //Read JPEG parameters from the buffer
  1521. jerr = ijlRead(&jcprops, IJL_JBUFF_READPARAMS);
  1522. }
  1523. //Make sure Parameter read was successful
  1524. if (jerr != IJL_OK)
  1525. {
  1526. MessageBox(g_hMainWnd, "Error reading JPEG parameters", TITLE, MB_OK);
  1527. return false;
  1528. }
  1529. //Prepare a 24Bit buffer to receive image data
  1530. BYTE *buffer24;
  1531. //Determine the required size
  1532. long szbuff24 = (jcprops.JPGWidth * C24BIT + 7) / 8
  1533. * jcprops.JPGHeight;
  1534. //Resize the buffer
  1535. buffer24 = new BYTE [szbuff24];
  1536. if (buffer24 == NULL)
  1537. {
  1538. MessageBox(g_hMainWnd, "Memory Allocation Error", TITLE, MB_OK);
  1539. return false;
  1540. }
  1541. //Set up the DIB specification for the JPEG decoder
  1542. jcprops.DIBWidth    = jcprops.JPGWidth;
  1543. jcprops.DIBHeight   = jcprops.JPGHeight; //Implies a bottom-up DIB.
  1544. jcprops.DIBChannels = 3;
  1545. jcprops.DIBColor    = IJL_BGR;
  1546. jcprops.DIBPadBytes = IJL_DIB_PAD_BYTES(jcprops.JPGWidth,3);
  1547. jcprops.DIBBytes    = reinterpret_cast<BYTE*>(buffer24);
  1548. //Set the JPG color space ... this will always be somewhat of an
  1549. //educated guess at best because JPEG is "color blind" (i.e.,
  1550. //nothing in the bit stream tells you what color space the data was
  1551. //encoded from. However, in this example we assume that we are
  1552. //reading JFIF files which means that 3 channel images are in the
  1553. //YCbCr color space and 1 channel images are in the Y color space.
  1554. switch(jcprops.JPGChannels)
  1555. {
  1556. case 1: jcprops.JPGColor = IJL_G;
  1557. break;
  1558. case 3: jcprops.JPGColor = IJL_YCBCR;
  1559. break;
  1560. default:
  1561. //This catches everything else, but no color twist will be
  1562. //performed by the IJL.
  1563. jcprops.DIBColor = (IJL_COLOR)IJL_OTHER;
  1564. jcprops.JPGColor = (IJL_COLOR)IJL_OTHER;
  1565. break;
  1566. }
  1567. //Read JPEG image data into our 24bit buffer
  1568. if (bFromFile)
  1569. jerr = ijlRead(&jcprops, IJL_JFILE_READWHOLEIMAGE);
  1570. else
  1571. jerr = ijlRead(&jcprops, IJL_JBUFF_READWHOLEIMAGE);
  1572. //Make sure the read was successful
  1573. if (jerr != IJL_OK)
  1574. {
  1575. MessageBox(g_hMainWnd, "Error reading JPEG image", TITLE, MB_OK);
  1576. return false;
  1577. }
  1578. HBITMAP hbm;
  1579. //Convert to current CLRMODE
  1580. if (DDPixelFormat.dwRGBBitCount == C16BIT)
  1581. {
  1582. //Create a 16bit buffer
  1583. WORD *buffer16;
  1584. long szbuff16;
  1585. //determine the size of our buffer
  1586. szbuff16 = ((jcprops.JPGWidth * C16BIT + 7) / 8)
  1587. * jcprops.JPGHeight;
  1588. //resize the buffer and make sure resize works
  1589. buffer16 = new WORD [szbuff16];
  1590. if (buffer16 == NULL)
  1591. {
  1592. MessageBox(g_hMainWnd, "Error creating 16Bit buffer", TITLE, MB_OK);
  1593. return false;
  1594. }
  1595. //Start at the beginning of the buffer
  1596. long j = 0;
  1597. //Step through the 24bit buffer
  1598. //Retrieve 3 channels at a time and convert their values to 16bit
  1599. for (long i = 0; i < szbuff24; i += 3)   
  1600. {
  1601. //Check the pixel format and write the color data
  1602. //to the 16bit buffer. After the write, advance the
  1603. //16bit buffer by one.
  1604. if (nPixelFormat == PF_555)
  1605. buffer16[j++] = RGB555(buffer24[i], buffer24[i + 1],
  1606. buffer24[i + 2]);
  1607. else
  1608. buffer16[j++] = RGB565(buffer24[i], buffer24[i + 1],
  1609. buffer24[i + 2]);
  1610. }
  1611. //Create the bitmap using the new 16bit buffer   
  1612. hbm = CreateBitmap (jcprops.JPGWidth, jcprops.JPGHeight, 1,
  1613. C16BIT, buffer16);
  1614. if(hbm == NULL)
  1615. {
  1616. MessageBox(g_hMainWnd, "Failed to create 16Bit Bitmap", TITLE, MB_OK);
  1617. return false;
  1618. }
  1619. //remove the new buffer
  1620. delete buffer16;
  1621. }
  1622. else if (DDPixelFormat.dwRGBBitCount == C24BIT)
  1623. {
  1624. //The data we have from the JPEG is already 24bit
  1625. //Just create the new bitmap from our buffer
  1626. hbm = CreateBitmap (jcprops.JPGWidth, jcprops.JPGHeight, 1,
  1627. C24BIT, buffer24);
  1628. if(hbm == NULL)
  1629. {
  1630. MessageBox(g_hMainWnd, "Failed to create 24Bit Bitmap", TITLE, MB_OK);
  1631. return false;
  1632. }
  1633. }
  1634. else if (DDPixelFormat.dwRGBBitCount == C32BIT)
  1635. {
  1636. //Create a 32bit buffer
  1637. BYTE *buffer32;
  1638. long szbuff32;
  1639. //determine the size of our buffer
  1640. szbuff32 = ((jcprops.JPGWidth * C32BIT + 7) / 8)
  1641. * jcprops.JPGHeight;
  1642. //resize the buffer and make sure resize works
  1643. buffer32 = new BYTE [szbuff32];
  1644. if (buffer32 == NULL)
  1645. {
  1646. MessageBox(g_hMainWnd, "Error creating 32Bit buffer", TITLE, MB_OK);
  1647. return false;
  1648. }
  1649. //Start at the beginning of the 24bit buffer
  1650. long j = 0;
  1651. //Step through the 32bit buffer, copying the 3 Channels from
  1652. //the 24bit buffer. However, at the end of each channel, we
  1653. //have to write an extra byte for the 32bit image's alpha
  1654. //channel
  1655. for (long i = 0; i < szbuff32; i += 4)   
  1656. {
  1657. buffer32[i + 0] = buffer24[j++]; //Blue channel
  1658. buffer32[i + 1] = buffer24[j++]; //Green channel
  1659. buffer32[i + 2] = buffer24[j++]; //Red channel
  1660. buffer32[i + 3] = (BYTE)0x00;    //Alpha channel
  1661. }
  1662. //Create the bitmap using the new 32bit buffer   
  1663. hbm = CreateBitmap (jcprops.JPGWidth, jcprops.JPGHeight, 1,
  1664. C32BIT, buffer32);
  1665. if(hbm == NULL)
  1666. {
  1667. MessageBox(g_hMainWnd, "Failed to create 32Bit Bitmap",
  1668. TITLE, MB_OK);
  1669. return false;
  1670. }
  1671. //remove the 32bit buffer
  1672. delete buffer32;
  1673. }
  1674. else
  1675. {
  1676. MessageBox(g_hMainWnd,
  1677. "Palettized modes not supported. Use a 16, 24, or 32 Bit display.",
  1678. TITLE, MB_OK);
  1679. return false;
  1680. }
  1681. //remove the old buffer
  1682. delete buffer24;
  1683. //If DirectDraw Surface is NULL, create it
  1684. if (*ppSurface == NULL)
  1685. {
  1686. //Create the surface from our surface description
  1687. Result = g_pDisplay->CreateSurface(ppSurface,jcprops.JPGWidth,jcprops.JPGHeight );
  1688. if(Result != DD_OK)
  1689. {
  1690. MessageBox(g_hMainWnd, "Could not create surface", TITLE, MB_OK);
  1691. return false;
  1692. }
  1693. }
  1694. //Copy bitmap data to DirectDraw Surface
  1695. (*ppSurface)->DrawBitmap(hbm, 0, 0, 0, 0);
  1696. // clean up and destroy the JPEG Decompressor
  1697. ijlFree(&jcprops);
  1698. DeleteObject(hbm);
  1699. return true;
  1700. }