赞
踩
头文件 GameEngine.h
- #pragma once
-
- #include<windows.h>
- #include<list>
- #include"Sprite.h"
- using namespace std;
-
- int WINAPI WINMAIN(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow);
-
- LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
-
- /*
- 以下函数的特定实现是游戏特有的,必须由使用该游戏引擎的各个游戏提供
- */
- BOOL GameInitialize(HINSTANCE hInstance);
- void GameStart(HWND hWindow);
- void GameEnd();
- void GameActivate(HWND hWindow);
- void GameDeactivate(HWND hWindow);
- void GamePaint(HDC hDC);
- void GameCycle();
- void HandleKeys();
- void MouseButtonDown(int x,int y,BOOL bLeft);
- void MouseButtonUp(int x,int y,BOOL bLeft);
- void MouseMove(int x,int y);
- BOOL SpriteCollision(Sprite* pSpriteHitter, Sprite* pSpriteHittee);
- void SpriteDying(Sprite* pSpriteDying);//游戏知道何时破坏子画面非常有用的。例如,在破坏一个流星子面面时,可以创建一个爆炸子画面。
- /*
- GameEngine类
- */
- class GameEngine{
- protected:
- static GameEngine *m_pGameEngine;
- HINSTANCE m_hInstance;
- HWND m_hWindow;
- TCHAR m_szWindowClass[32];
- TCHAR m_szTitle[32];
- WORD m_wIcon,m_wSmallIcon;
- int m_iWidth,m_iHeight;
- int m_iFrameDelay;
- BOOL m_bSleep;
- list<Sprite*> m_vSprites;
- UINT m_uiMIDIPlayerID;
- // Helper Methods
- BOOL CheckSpriteCollision(Sprite* pTestSprite);
- public:
- //构造函数、析构函数
- GameEngine(HINSTANCE hInstance, LPTSTR szWindowClass, LPTSTR szTitle,
- WORD wIcon, WORD wSmallIcon, int iWidth = 640, int iHeight = 480);
- virtual ~GameEngine();
- //常规方法
- static GameEngine* GetEngine(){return m_pGameEngine;}
- BOOL Initialize(int iCmdShow);
- LRESULT HandleEvent(HWND hWindow,UINT msg, WPARAM wParam, LPARAM lParam);
- void AddSprite(Sprite* pSprite);
- void DrawSprites(HDC hDC);
- void UpdateSprites();
- void CleanupSprites();
- Sprite* IsPointInSprite(int x, int y);
- void PlayMIDISong(LPTSTR szMIDIFileName = TEXT(""),BOOL bRestart = TRUE);
- void PauseMIDISong();
- void CloseMIDIPlayer();
- //访问方法
- HINSTANCE GetInstance(){return m_hInstance;}
- HWND GetWindow(){return m_hWindow;}
- void SetWindow(HWND hWindow){m_hWindow = hWindow;}
- LPTSTR GetTitle(){return m_szTitle;}
- WORD GetIcon(){return m_wIcon;}
- WORD GetSmallIcon(){return m_wSmallIcon;}
- int GetWidth(){return m_iWidth;}
- int GetHeight(){return m_iHeight;}
- int GetFrameDelay(){return m_iFrameDelay;}
- void SetFrameRate(int iFrameRate){m_iFrameDelay = 1000/iFrameRate;}
- BOOL GetSleep(){return m_bSleep;}
- void SetSleep(BOOL bSleep){m_bSleep = bSleep;}
- };
GameEngine.cpp
- #include "GameEngine.h"
-
- //静态变量初始
- GameEngine *GameEngine::m_pGameEngine = NULL;
-
- //windows函数
- int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,PSTR szCmdLine, int iCmdShow){
- MSG msg;
- static int iTickTrigger = 0;
- int iTickCount;
- if(GameInitialize(hInstance)){
- //初始化游戏引擎
- if(!GameEngine::GetEngine()->Initialize(iCmdShow)){
- return false;
- }
-
- //进入主消息循环
- while(TRUE){
- if(PeekMessage(&msg,NULL,0,0,PM_REMOVE)){
- //处理消息
- if(msg.message == WM_QUIT){
- break;
- }
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }else{
- //确保游戏引擎没有休眠
- if(!GameEngine::GetEngine()->GetSleep()){
- //检查滴答计数,查看是否过了一个游戏周期
- /*
- note:这里看不太懂,为什么iTickTrigger在iTickCount上不断加一个FrameDelay。
- iTickCount和iTickTrigger为什么不用模运算呢?
- */
- iTickCount = GetTickCount();
- if(iTickCount > iTickTrigger){
- iTickTrigger = iTickCount + GameEngine::GetEngine()->GetFrameDelay();
- HandleKeys();
- GameCycle();
- }
- }
- }
- }
- return (int)msg.wParam;
- }
- GameEnd();
- return TRUE;
- }
-
- LRESULT CALLBACK WndProc(HWND hWindow, UINT msg, WPARAM wParam, LPARAM lParam){
- //将所有windows消息都传递给游戏引擎
- return GameEngine::GetEngine()->HandleEvent(hWindow,msg,wParam,lParam);
-
- }
- //-----------------------------------------------------------------
- // Game Engine Helper Methods
- //-----------------------------------------------------------------
- BOOL GameEngine::CheckSpriteCollision(Sprite* pTestSprite)
- {
- // See if the sprite has collided with any other sprites
- list<Sprite*>::iterator siSprite;
- for (siSprite = m_vSprites.begin(); siSprite != m_vSprites.end(); siSprite++)
- {
- // Make sure not to check for collision with itself
- if (pTestSprite == (*siSprite))
- continue;
-
- // Test the collision
- if (pTestSprite->TestCollision(*siSprite))
- // Collision detected
- return SpriteCollision((*siSprite), pTestSprite);
- }
- // No collision
- return FALSE;
- }
- /*
- GameEngine的构造函数、析构函数
- */
- GameEngine::GameEngine(HINSTANCE hInstance,LPTSTR szWindowClass,LPTSTR szTitle, WORD wIcon,WORD wSmallIcon, int iWidth, int iHeight){
- //设置游戏引擎的成员变量
- m_pGameEngine = this;
- m_hInstance = hInstance;
- /*
- note: why m_hWindow = NULL?
- */
- m_hWindow = NULL;
- if(lstrlen(szWindowClass)>0){
- lstrcpy(m_szWindowClass, szWindowClass);
- }
- if(lstrlen(szTitle)>0){
- lstrcpy(m_szTitle,szTitle);
- }
- m_wIcon = wIcon;
- m_wSmallIcon = wSmallIcon;
- m_iWidth = iWidth;
- m_iHeight = iHeight;
- m_iFrameDelay = 50; //默认为20帧/秒
- m_bSleep = TRUE;
- m_uiMIDIPlayerID = 0;
- }
- GameEngine::~GameEngine(){
-
- }
-
- /*
- 游戏引擎常规方法
- */
- BOOL GameEngine::Initialize(int iCmdShow){
- WNDCLASSEX wndclass;
- //创建主窗口的窗口类
- wndclass.cbSize = sizeof(wndclass);
- wndclass.style = CS_HREDRAW | CS_VREDRAW;
- wndclass.lpfnWndProc = WndProc;
- wndclass.cbClsExtra = 0;
- wndclass.cbWndExtra = 0;
- wndclass.hInstance = m_hInstance;
- wndclass.hIcon = LoadIcon(m_hInstance,MAKEINTRESOURCE(GetIcon()));
- wndclass.hIconSm = LoadIcon(m_hInstance,MAKEINTRESOURCE(GetSmallIcon()));
- wndclass.hCursor = LoadCursor(NULL,IDC_ARROW);
- wndclass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
- wndclass.lpszMenuName = NULL;
- wndclass.lpszClassName = m_szWindowClass;
-
- //注册窗口类
- if(!RegisterClassEx(&wndclass))
- return FALSE;
-
- //根据游戏大小计算窗口大小和位置
- int iWindowWidth = m_iWidth + GetSystemMetrics(SM_CXFIXEDFRAME) * 2;
- int iWindowHeight = m_iHeight + GetSystemMetrics(SM_CYFIXEDFRAME) * 2 + GetSystemMetrics(SM_CYCAPTION);;
- if(wndclass.lpszMenuName != NULL) iWindowHeight += GetSystemMetrics(SM_CYMENU);
- int iXWindowPos = (GetSystemMetrics(SM_CXSCREEN)-iWindowWidth)/2;
- int iYWindowPos = (GetSystemMetrics(SM_CYSCREEN)-iWindowHeight)/2;
-
- //创建窗口
- m_hWindow = CreateWindow(m_szWindowClass,m_szTitle,WS_POPUPWINDOW|
- WS_CAPTION|WS_MINIMIZEBOX, iXWindowPos,iYWindowPos, iWindowWidth,iWindowHeight, NULL,NULL, m_hInstance, NULL);
- if(!m_hWindow) return FALSE;
-
- ShowWindow(m_hWindow,iCmdShow);
- UpdateWindow(m_hWindow);
-
- return TRUE;
- }
-
- LRESULT GameEngine::HandleEvent(HWND hWindow, UINT msg, WPARAM wParam,LPARAM lParam){
- //将Windows消息传递给游戏引擎成员函数
- switch(msg){
- case WM_CREATE:
- //设置游戏窗口并开始游戏
- SetWindow(hWindow);
- GameStart(hWindow);
- return 0;
- case WM_SETFOCUS:
- //激活游戏并更新休眠状态
- GameActivate(hWindow);
- SetSleep(FALSE);
- return 0;
- case WM_KILLFOCUS:
- //停用游戏并更新休眠状态
- GameDeactivate(hWindow);
- SetSleep(TRUE);
- return 0;
- case WM_PAINT:
- HDC hDC;
- PAINTSTRUCT ps;
- hDC = BeginPaint(hWindow,&ps);
-
- //绘制游戏
- GamePaint(hDC);
-
- EndPaint(hWindow,&ps);
- return 0;
- //鼠标事件
- case WM_LBUTTONDOWN:
- MouseButtonDown(LOWORD(lParam),HIWORD(lParam),TRUE);
- return 0;
- case WM_LBUTTONUP:
- MouseButtonUp(LOWORD(lParam),HIWORD(lParam),TRUE);
- case WM_RBUTTONDOWN:
- MouseButtonDown(LOWORD(lParam),HIWORD(lParam),FALSE);
- return 0;
- case WM_RBUTTONUP:
- MouseButtonUp(LOWORD(lParam),HIWORD(lParam),FALSE);
- return 0;
- case WM_MOUSEMOVE:
- MouseMove(LOWORD(lParam),HIWORD(lParam));
- return 0;
- case WM_DESTROY:
- //结束游戏并退出应用程序
- GameEnd();
- PostQuitMessage(0);
- return 0;
- }
- return DefWindowProc(hWindow,msg,wParam,lParam);
- }
-
-
- void GameEngine::AddSprite(Sprite* pSprite){
- // Add a sprite to the sprite list
- if (pSprite != NULL){
- // See if there are sprites already in the sprite list
- if (m_vSprites.size() > 0){
- // Find a spot in the sprite list to insert the sprite by its z-order
- list<Sprite*>::iterator siSprite;
- for (siSprite = m_vSprites.begin(); siSprite != m_vSprites.end(); siSprite++){
- if (pSprite->GetZOrder() < (*siSprite)->GetZOrder()){
- // Insert the sprite into the sprite vector
- m_vSprites.insert(siSprite, pSprite);
- return;
- }
- }
- }
-
- // The sprite's z-order is highest, so add it to the end of the list
- m_vSprites.push_back(pSprite);
- }
- }
-
- void GameEngine::DrawSprites(HDC hDC)
- {
- // Draw the sprites in the sprite list
- list<Sprite*>::iterator siSprite;
- for (siSprite = m_vSprites.begin(); siSprite != m_vSprites.end(); siSprite++)
- (*siSprite)->Draw(hDC);
- }
-
- void GameEngine::UpdateSprites()
- {
- // Update the sprites in the sprite list
- RECT rcOldSpritePos;
- SPRITEACTION saSpriteAction;
- list<Sprite*>::iterator siSprite;
- for (siSprite = m_vSprites.begin(); siSprite != m_vSprites.end();)
- {
- // Save the old sprite position in case we need to restore it
- rcOldSpritePos = (*siSprite)->GetPosition();
-
- // Update the sprite
- saSpriteAction = (*siSprite)->Update();
-
- // Handle the SA_ADDSPRITE sprite action
- if (saSpriteAction & SA_ADDSPRITE)
- // Allow the sprite to add its sprite
- AddSprite((*siSprite)->AddSprite());
-
- // Handle the SA_KILL sprite action
- if (saSpriteAction & SA_KILL)
- {
- //Notify the game that the sprite is dying
- SpriteDying(*siSprite);
- //Kill the sprite
- delete (*siSprite);
- siSprite = m_vSprites.erase(siSprite);
- continue;
- }
-
- // See if the sprite collided with any others
- if (CheckSpriteCollision(*siSprite)){
- // Restore the old sprite position
- (*siSprite)->SetPosition(rcOldSpritePos);
- }
- ++siSprite;
- }
- }
-
- void GameEngine::CleanupSprites(){
- // Delete and remove the sprites in the sprite list
- while(!m_vSprites.empty()){
- delete(m_vSprites.back());
- m_vSprites.pop_back();
- }
- }
-
- Sprite* GameEngine::IsPointInSprite(int x, int y){
- // See if the point is in a sprite in the sprite list
- list<Sprite*>::reverse_iterator siSprite;
- for (siSprite = m_vSprites.rbegin(); siSprite != m_vSprites.rend(); siSprite++)
- if (!(*siSprite)->IsHidden() && (*siSprite)->IsPointInside(x, y))
- return (*siSprite);
-
- // The point is not in a sprite
- return NULL;
- }
-
- void GameEngine::PlayMIDISong(LPTSTR szMIDIFileName, BOOL bRestart)
- {
- // See if the MIDI player needs to be opened
- if (m_uiMIDIPlayerID == 0){
- // Open the MIDI player by specifying the device and filename
- MCI_OPEN_PARMS mciOpenParms;
- mciOpenParms.lpstrDeviceType = TEXT("sequencer");
- mciOpenParms.lpstrElementName = szMIDIFileName;
- if (mciSendCommand(NULL, MCI_OPEN, MCI_OPEN_TYPE | MCI_OPEN_ELEMENT,
- (DWORD_PTR)&mciOpenParms) == 0){
- // Get the ID for the MIDI player
- m_uiMIDIPlayerID = mciOpenParms.wDeviceID;
- }else{
- // There was a problem, so just return
- return;
- }
- }
-
- // Restart the MIDI song, if necessary
- if (bRestart)
- {
- MCI_SEEK_PARMS mciSeekParms;
- if (mciSendCommand(m_uiMIDIPlayerID, MCI_SEEK, MCI_SEEK_TO_START,
- (DWORD_PTR)&mciSeekParms) != 0)
- // There was a problem, so close the MIDI player
- CloseMIDIPlayer();
- }
-
- // Play the MIDI song
- MCI_PLAY_PARMS mciPlayParms;
- if (mciSendCommand(m_uiMIDIPlayerID, MCI_PLAY, 0,
- (DWORD_PTR)&mciPlayParms) != 0)
- // There was a problem, so close the MIDI player
- CloseMIDIPlayer();
- }
-
- void GameEngine::PauseMIDISong()
- {
- // Pause the currently playing song, if possible
- if (m_uiMIDIPlayerID != 0)
- mciSendCommand(m_uiMIDIPlayerID, MCI_PAUSE, 0, NULL);
- }
-
- void GameEngine::CloseMIDIPlayer()
- {
- // Close the MIDI player, if possible
- if (m_uiMIDIPlayerID != 0)
- {
- mciSendCommand(m_uiMIDIPlayerID, MCI_CLOSE, 0, NULL);
- m_uiMIDIPlayerID = 0;
- }
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。