天行健 君子当自强而不息

创建游戏内核(2)


本篇是的 创建游戏内核(1)续篇,并且以 游戏程序流、状态处理机、进程管理器、数据包系统的实现中介绍的状态处理机的实现为基础。

新的状态管理器引入了两个概念:调用目的以及添加一个用户自定义的数据指针,此指针指向STATE_MANAGER中的函数。调用目的是一个状态被调用的原因,“目的(purpose)”可以是INIT_PURPOSE(表明要使用函数,需要事先进行准备)、FRAME_PURPOSE(处理单独的一帧)或SHUTDOWN_PURPOSE(在处理完成时释放所有资源)。

点击下载源码和工程

以下是该类的定义:
 
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);
};

接着是该类的实现:
 
//-----------------------------------------------------------------------------
// 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;
}
 

下面给出测试代码:

注意,加上一个用户自定义变量data_ptr是有根据的。因为在类中,必须将状态函数声明为静态(否则编译器会报错)。因此需要传递一个指向状态函数的指针,状态函数仍然是类的一部分,因此状态函数就可以使用指针自由地访问类的数据(甚至是私有数据)。
 
/*****************************************************************************
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();
}

运行截图:



阅读下篇:创建游戏内核(3)

posted on 2007-08-25 21:29 lovedday 阅读(540) 评论(0)  编辑 收藏 引用


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


公告

导航

统计

常用链接

随笔分类(178)

3D游戏编程相关链接

搜索

最新评论