游戏引擎及其简单实现
游戏引擎负责处理各种琐碎事务:组件游戏,确保它正确运行及关闭它。将游戏分解为事件:
下面这些事件只适用于任何游戏的部分核心事件:
● 初始化
● 启动
● 结束
● 激活
● 停用
● 绘制
● 循环
初始化事件在一开始运行游戏时发生,这时游戏执行重要的初始设置任务,包括创建游戏引擎本身。启动和结束事件对应于游戏的开始和结束,这时很适合执行与特定的游戏会话相关联的初始化和清理任务。在最小化游戏或者将其发送至后台,然后在恢复时,就将发生激活和停用事件。当游戏需要绘制自身时,将发送绘制事件,类似于WINDOWS WM_PAINT 消息。最后,循环事件使游戏执行一个单独的游戏周期,它非常重要。
游戏的计时机制:游戏在指定的时间内运行的周期越多,看起来就越平滑。事实上,大多数游戏设置都在15 - 16周期每秒的范围内,最快的速度可能达到30周期每秒,比电影还快。除了极少数的一些情况外,应该力求达到的最低速度设置为12周期每秒。
游戏引擎的类:
#ifndef _GAMEENGINE_H
#define
_GAMEENGINE_H
#include
<
windows.h
>
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
//
游戏事件
BOOL GameInitialize(HINSTANCE hInstance);
//
初始化
void
GameStart(HWND hWnd);
//
启动
void
GameEnd();
//
结束
void
GameActivate(HWND hWnd);
//
激活
void
GameDeactivate(HWND hWnd);
//
停用
void
GamePaint(HDC hdc);
//
绘制
void
GameCycle();
//
循环
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
//
游戏引擎类
class
GameEngine
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
protected:
static GameEngine * m_pGameEngine; //指向自身的静态指针
HINSTANCE m_hInstance; //实例句柄
HWND m_hWnd; //窗口句柄
TCHAR m_szWndClass[32]; //窗口类名
TCHAR m_szTitle[32]; //标题
WORD m_wIcon,m_wSmallIcon; //大小图标
int m_iWidth,m_iHeight; //游戏区的宽和高
int m_iFrameDelay; //帧的延迟时间(ms)
BOOL m_bSleep; //休眠状态
public:
GameEngine(HINSTANCE hInstance,LPTSTR szWndClass,LPTSTR szTitle,
WORD wIcon,WORD wSmallIcon,int iWidth=640,int iHeight=480);
~GameEngine();
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
static GameEngine * GetEngine() ...{ return m_pGameEngine;};
BOOL Initialize(int iCmdShow);
LRESULT HandlEvent(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam);
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
HINSTANCE GetInstance() ...{ return m_hInstance ;};
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
HWND GetWindow() ...{ return m_hWnd;};
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
void SetWindow(HWND hWnd)...{ m_hWnd=hWnd ;};
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
LPSTR GetTitle()...{ return m_szTitle ;};
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
WORD GetIcon() ...{ return m_wIcon;};
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
WORD GetSmallIcon() ...{ return m_wSmallIcon; };
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
int GetWidth() ...{ return m_iWidth;};
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
int GetHeight() ...{ return m_iHeight;};
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
int GetFrameDelay() ...{ return m_iFrameDelay ;};
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
void SetFrameDelay(int iFrameRate)...{ m_iFrameDelay=1000/iFrameRate;};
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
BOOL GetSleep()...{ return m_bSleep;};
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
void SetSleep(BOOL bSleep)...{ m_bSleep=bSleep;};
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
}
;
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
LRESULT CALLBACK WndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam);
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
#endif
其实现文件如下:
#include
"
GameEngine.h
"
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
//
静态成员初始化
GameEngine
*
GameEngine::m_pGameEngine
=
NULL;
//
构造成员函数
GameEngine::GameEngine(HINSTANCE hInstance,LPSTR szWndClass,LPSTR szTitle,
WORD wIcon,WORD wSmallIcon,
int
iWidth,
int
iHeight)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
m_pGameEngine=this;
m_hInstance=hInstance;
m_hWnd=NULL;
if(lstrlen(szWndClass)>0)
lstrcpy(m_szWndClass,szWndClass);
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;
}
//
析构成员函数
GameEngine::
~
GameEngine()
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
}
//
引擎初始化
BOOL GameEngine::Initialize(
int
iCmdShow)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
WNDCLASSEX wc;
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
//创建主窗口的类
wc.cbSize=sizeof(WNDCLASSEX);
wc.style=CS_HREDRAW|CS_VREDRAW;
wc.lpfnWndProc=WndProc;
wc.cbClsExtra=0;
wc.cbWndExtra=0;
wc.hbrBackground=(HBRUSH)(COLOR_WINDOW+1);
wc.hCursor=LoadCursor(NULL,IDC_ARROW);
wc.hIcon=LoadIcon(m_hInstance,MAKEINTRESOURCE(GetIcon()));
wc.hIconSm=LoadIcon(m_hInstance,MAKEINTRESOURCE(GetSmallIcon()));
wc.hInstance=m_hInstance;
wc.lpszClassName=m_szWndClass;
wc.lpszMenuName=NULL;
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
//注册窗口类
if(!RegisterClassEx(&wc))
return FALSE;
//根据游戏大小计算窗口大小和位置
int iWindowWidth=m_iWidth+GetSystemMetrics(SM_CXFIXEDFRAME)*2;
int iWindowHeight=m_iHeight+GetSystemMetrics(SM_CYFIXEDFRAME)*2+GetSystemMetrics(SM_CYCAPTION);
if(wc.lpszMenuName!=NULL)
iWindowHeight+=GetSystemMetrics(SM_CYMENU);
int iXWindowPos=(GetSystemMetrics(SM_CXSCREEN)-iWindowWidth)/2;
int iYWindowPos=(GetSystemMetrics(SM_CYSCREEN)-iWindowHeight)/2;
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
//创建窗口
m_hWnd=CreateWindow(m_szWndClass,m_szTitle,WS_POPUPWINDOW|WS_CAPTION|WS_MINIMIZEBOX,iXWindowPos,iYWindowPos,
iWindowWidth,iWindowHeight,NULL,NULL,m_hInstance,NULL);
if(!m_hWnd)
return FALSE;
//显示和更新窗口
ShowWindow(m_hWnd,iCmdShow);
UpdateWindow(m_hWnd);
return TRUE;
}
//
游戏消息处理函数
LRESULT GameEngine::HandlEvent(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
switch(msg)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
case WM_CREATE:
//设置游戏窗口并开始游戏
SetWindow(hWnd);
GameStart(hWnd);
return 0;
case WM_SETFOCUS:
//激活游戏并更新休眠状态
GameActivate(hWnd);
SetSleep(FALSE);
return 0;
case WM_KILLFOCUS:
//停用游戏并更新休眠状态
GameDeactivate(hWnd);
SetSleep(TRUE);
return 0;
case WM_PAINT:
HDC hDc;
PAINTSTRUCT ps;
hDc=BeginPaint(hWnd,&ps);
//绘制游戏
GamePaint(hDc);
EndPaint(hWnd,&ps);
return 0;
case WM_DESTROY:
//结束游戏
GameEnd();
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWnd,msg,wParam,lParam);
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
LRESULT CALLBACK WndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
return GameEngine::GetEngine()->HandlEvent(hWnd,msg,wParam,lParam);
}
//
主函数入口
int
WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPreInstance,PSTR szCommandLine,
int
iCmdShow )
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
MSG msg;
static int iTickTriger=0;
int iTickCount;
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
if(GameInitialize(hInstance))
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
if(!GameEngine::GetEngine()->Initialize(iCmdShow))
return FALSE;
while(TRUE)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
if(PeekMessage(&msg,NULL,0,0,PM_REMOVE))
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
if(msg.message==WM_QUIT)
break;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
//确保游戏引擎没有休眠
if(!GameEngine::GetEngine()->GetSleep())
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
//检查滴答计数,查看是否经历了一个周期
iTickCount=GetTickCount();
if(iTickCount>iTickTriger)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
iTickTriger=iTickCount+GameEngine::GetEngine()->GetFrameDelay();
//游戏循环
GameCycle();
}
}
}
}
}
//游戏结束
GameEnd();
return TRUE;
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
其使用方法:
xxx.h文件要先声明一个全局游戏引擎指针。
#include
"
resource.h
"
#include
"
GameEngine.h
"
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
GameEngine
*
g_pGame;
//
全局游戏引擎指针
然后xxx.cpp文件包含该xxx.h文件,在实现相应的游戏事件:
#include
"
Blizzard.h
"
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
BOOL GameInitialize(HINSTANCE hInstance)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
g_pGame=new GameEngine(hInstance,TEXT("PRIZE"),TEXT("PRIZE"),IDI_PRIZE,IDI_PRIZE);
if(g_pGame==NULL)
return FALSE;
g_pGame->SetFrameDelay(15);
return TRUE;
}
void
GameStart(HWND hWnd)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
srand(GetTickCount());
}
void
GameEnd()
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
}
void
GameActivate(HWND hWnd)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
HDC hDc;
RECT rect;
GetClientRect(hWnd,&rect);
hDc=GetDC(hWnd);
DrawText(hDc,"Here comes ....",-1,&rect,DT_SINGLELINE|DT_CENTER|DT_VCENTER);
ReleaseDC(hWnd,hDc);
}
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
void
GameDeactivate(HWND hWnd)
...
{}
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
void
GamePaint(HDC hdc)
...
{}
void
GameCycle()
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
HDC hDc;
HWND hWnd=g_pGame->GetWindow();
hDc=GetDC(hWnd);
DrawIcon(hDc,rand()%g_pGame->GetWidth(),rand()%g_pGame->GetHeight(),(HICON)(WORD)GetClassLong(hWnd,GCL_HICON));
ReleaseDC(hWnd,hDc);
}
转自:http://www.cnblogs.com/mywolrd/archive/2008/02/27/1930742.html