本篇是的
創(chuàng)建游戲內(nèi)核(1)續(xù)篇,并且以
游戲程序流、狀態(tài)處理機(jī)、進(jìn)程管理器、數(shù)據(jù)包系統(tǒng)的實(shí)現(xiàn)中介紹的狀態(tài)處理機(jī)的實(shí)現(xiàn)為基礎(chǔ)。
新的狀態(tài)管理器引入了兩個(gè)概念:調(diào)用目的以及添加一個(gè)用戶自定義的數(shù)據(jù)指針,此指針指向STATE_MANAGER中的函數(shù)。調(diào)用目的是一個(gè)狀態(tài)被調(diào)用的原因,“目的(purpose)”可以是INIT_PURPOSE(表明要使用函數(shù),需要事先進(jìn)行準(zhǔn)備)、FRAME_PURPOSE(處理單獨(dú)的一幀)或SHUTDOWN_PURPOSE(在處理完成時(shí)釋放所有資源)。
點(diǎn)擊下載源碼和工程
以下是該類的定義:
enum PURPOSE
{
NO_PURPOSE = 0,
INIT_PURPOSE,
SHUTDOWN_PURPOSE,
FRAME_PURPOSE
};
typedef void (*FUNC_PTR)(void* func_ptr, long purpose);
//==========================================================================
// Defines for state manager.
//==========================================================================
class STATE_MANAGER
{
private:
struct STATE
{
FUNC_PTR func;
STATE* next;
STATE()
{
func = NULL;
next = NULL;
}
~STATE()
{
delete next;
next = NULL;
}
};
protected:
STATE* _state_parent;
public:
STATE_MANAGER();
~STATE_MANAGER();
void Push(FUNC_PTR func_ptr, void* data_ptr = NULL);
BOOL Pop(void* data_ptr = NULL);
void Pop_All(void* data_ptr = NULL);
BOOL Process(void* data_ptr = NULL);
};
接著是該類的實(shí)現(xiàn):
//-----------------------------------------------------------------------------
// Constructor, initialize state pointer which pointer to parent state.
//-----------------------------------------------------------------------------
STATE_MANAGER::STATE_MANAGER()
{
_state_parent = NULL;
}
//-----------------------------------------------------------------------------
// Destructor, pop off all functions.
//-----------------------------------------------------------------------------
STATE_MANAGER::~STATE_MANAGER()
{
Pop_All();
}
//-----------------------------------------------------------------------------
// Push a function on to the stack.
//-----------------------------------------------------------------------------
void STATE_MANAGER::Push(FUNC_PTR func, void *data_ptr)
{
// don't push a NULL value
if(func != NULL)
{
// allocate a new state and push it on stack
STATE* state_ptr = new STATE();
state_ptr->func = func;
state_ptr->next = _state_parent;
_state_parent = state_ptr;
// call state with init purpose
state_ptr->func(data_ptr, INIT_PURPOSE);
}
}
//-----------------------------------------------------------------------------
// Pop a functoin off the stack.
//-----------------------------------------------------------------------------
BOOL STATE_MANAGER::Pop(void *data_ptr)
{
STATE* state_ptr;
// remove the head of stack (if any)
if((state_ptr = _state_parent) != NULL)
{
// first call with shutdown purpose
_state_parent->func(data_ptr, SHUTDOWN_PURPOSE);
_state_parent = state_ptr->next;
state_ptr->next = NULL;
delete state_ptr;
}
// return TRUE if more states exist, FALSE otherwise.
return (_state_parent != NULL);
}
//-----------------------------------------------------------------------------
// Pop all functions off the stack.
//-----------------------------------------------------------------------------
void STATE_MANAGER::Pop_All(void *data_ptr)
{
while(Pop(data_ptr) == TRUE)
;
}
//-----------------------------------------------------------------------------
// Process top-most function.
//-----------------------------------------------------------------------------
BOOL STATE_MANAGER::Process(void* data_ptr)
{
// return an error if no more states
if(_state_parent == NULL)
return FALSE;
// procress the top-most state
_state_parent->func(data_ptr, FRAME_PURPOSE);
return TRUE;
}
下面給出測試代碼:
注意,加上一個(gè)用戶自定義變量data_ptr是有根據(jù)的。因?yàn)樵陬愔校仨殞顟B(tài)函數(shù)聲明為靜態(tài)(否則編譯器會(huì)報(bào)錯(cuò))。因此需要傳遞一個(gè)指向狀態(tài)函數(shù)的指針,狀態(tài)函數(shù)仍然是類的一部分,因此狀態(tài)函數(shù)就可以使用指針自由地訪問類的數(shù)據(jù)(甚至是私有數(shù)據(jù))。
/*****************************************************************************
PURPOSE:
Test for class STATE_MANAGER.
*****************************************************************************/
#include "Core_System.h"
#pragma warning(disable : 4996)
class APP : public APPLICATION
{
private:
STATE_MANAGER _state_manager;
static void _Function1(void*, long);
static void _Function2(void*, long);
public:
BOOL Init()
{
_state_manager.Push(_Function1, this);
return TRUE;
}
};
void APP::_Function1(void* data_ptr, long purpose)
{
// get an instance pointer to APP
APP* app_inst = (APP*) data_ptr;
// if init purpose, show message box and push second function.
if(purpose == INIT_PURPOSE)
{
MessageBox(app_inst->Get_Hwnd(), "State1", "Message", MB_OK);
app_inst->_state_manager.Push(_Function2, app_inst);
return;
}
// if frame purpose, pop off function.
if(purpose == FRAME_PURPOSE)
app_inst->_state_manager.Pop(app_inst);
}
void APP::_Function2(void* data_ptr, long purpose)
{
APP* app_inst = (APP*) data_ptr;
if(purpose == FRAME_PURPOSE)
{
MessageBox(app_inst->Get_Hwnd(), "State 2", "Message", MB_OK);
app_inst->_state_manager.Pop(app_inst);
}
}
int PASCAL WinMain(HINSTANCE inst, HINSTANCE, LPSTR cmd_line, int cmd_show)
{
APP app;
return app.Run();
}
運(yùn)行截圖:
閱讀下篇:
創(chuàng)建游戲內(nèi)核(3)