CGameProcedure::InitStaticMemeber首先创建随机数发生器,然后调用g_theKernel.ReisgerClass来注册各种管理器及子系统。代码如下:
VOID CGameProcedure::InitStaticMemeber(VOID)
{
//初始化随即变量种子
srand( (unsigned)timeGetTime() );
g_theKernel.ReisgerClass(GETCLASS(tNode));// 注册本地类
g_theKernel.ReisgerClass(GETCLASS(CNetManager));//网络管理器
g_theKernel.ReisgerClass(GETCLASS(CWorldManager)); //场景管理器
//物体管理器
g_theKernel.ReisgerClass(GETCLASS(CObjectManager));
g_theKernel.ReisgerClass(GETCLASS(CObject));
g_theKernel.ReisgerClass(GETCLASS(CObject_Surface));
g_theKernel.ReisgerClass(GETCLASS(CObject_Effect));
g_theKernel.ReisgerClass(GETCLASS(CObject_Bullet));
//g_theKernel.ReisgerClass(GETCLASS(CObject_SkillObj));
g_theKernel.ReisgerClass(GETCLASS(CObject_Special));
g_theKernel.ReisgerClass(GETCLASS(CObject_Map));
g_theKernel.ReisgerClass(GETCLASS(CObject_Static));
g_theKernel.ReisgerClass(GETCLASS(CObject_Building));
g_theKernel.ReisgerClass(GETCLASS(CObject_Dynamic));
g_theKernel.ReisgerClass(GETCLASS(CObject_Character));
g_theKernel.ReisgerClass(GETCLASS(CObject_PlayerMySelf));
g_theKernel.ReisgerClass(GETCLASS(CObject_PlayerNPC));
g_theKernel.ReisgerClass(GETCLASS(CObject_PlayerOther));
g_theKernel.ReisgerClass(GETCLASS(CObject_ProjTex));
g_theKernel.ReisgerClass(GETCLASS(CObject_ProjTex_MouseTarget));
g_theKernel.ReisgerClass(GETCLASS(CObject_ProjTex_AuraDure));
g_theKernel.ReisgerClass(GETCLASS(CTripperObject_Transport));
g_theKernel.ReisgerClass(GETCLASS(CTripperObject_ItemBox));
g_theKernel.ReisgerClass(GETCLASS(CTripperObject_Resource));
g_theKernel.ReisgerClass(GETCLASS(CTripperObject_Platform));
g_theKernel.ReisgerClass(GETCLASS(CInputSystem));//输入管理器
g_theKernel.ReisgerClass(GETCLASS(tTimeSystem));//计时器
g_theKernel.ReisgerClass(GETCLASS(CSoundSystemFMod));//声音管理器
g_theKernel.ReisgerClass(GETCLASS(CDataBaseSystem));//数据库管理器
g_theKernel.ReisgerClass(GETCLASS(CVariableSystem));//变量管理器
g_theKernel.ReisgerClass(GETCLASS(CGameInterface));//UI操作接口
g_theKernel.ReisgerClass(GETCLASS(CUIDataPool));//UI数据池
g_theKernel.ReisgerClass(GETCLASS(CDataPool));
g_theKernel.ReisgerClass(GETCLASS(CCursorMng));//UI鼠标操作类
g_theKernel.ReisgerClass(GETCLASS(CScriptSystem));//脚本系统
g_theKernel.ReisgerClass(GETCLASS(CEventSystem));//事件系统
g_theKernel.ReisgerClass(GETCLASS(CActionSystem));//操作管理
g_theKernel.ReisgerClass(GETCLASS(CFakeObjSystem));//UI模型显示管理
g_theKernel.ReisgerClass(GETCLASS(CHelperSystem));//外接帮助系统
...//省略
}
由上面的代码可以看到,g_theKernel是存放游戏核心数据的一个全局变量,它是在Global.cpp中声明的。我们来看一下代码:
#include "StdAfx.h"
#include "Global.h"
tKernel g_theKernel;//数据核心
HWND g_hMainWnd = NULL;//主窗口
HINSTANCE g_hInstance = NULL;//当前主程序模块句柄
const CHAR VERSION_INFO[] = "0.0.0005";//当前版本号
const CHAR GAME_TITLE[] ="武侠世界";//标题
可以看到,除了数据核心之外,还有主窗口句柄、主程序模块句柄、主窗口标题以及版本信息等全局变量。g_theKernel在这声明为tKernel类。
我们先来了解一下tKernel类的成员变量。它定义在TDKernel.h文件中。
protected:
std::map< STRING, tClass* > m_ClassMap;//全局定义类检索表
tClass* m_pFirstClass; //类检索表中第一个类
tNode m_theRoot; //根节点
//插件信息
struct PLUGIN_INFO
{
HMODULE hModule;
STRING strPluginFile;
FUNC_DLLINIT pfnDllInit;
FUNC_DLLRELEASE pfnDllRelease;
};
std::vector< PLUGIN_INFO > m_vAllPlugin;//所有插件
static tKernel* s_pMe;//指向自己的指针
由上面的代码可以看出,tKernel类存放了三种数据,一是全局类的信息,二是插件的信息,三是指向自己的指针。我们重点看一下前两种。由于插件信息的数据结构比较简单,我们先来看一下。PLUGIN_INFO结构中记录了dll句柄,dll文件名,以及dll初始化以及释放的两个函数指针。所有的插件,都以PLUGIN_INFO的结构存放在vector容器之中。
至于全局类信息的存储,利用了tClass和tNode两种类型以及类名到类指针的映射表std::map< STRING, tClass* >。
class tNode
{
public:
tNode(VOID);
tNode(LPCTSTR szName);
virtual ~tNode() { Release(); }
virtual INT GetChildNum(VOID) const
{ return (INT)m_ChildBuf.size(); } //返回子节点数目
virtual const STRING& GetNodeName(VOID) const
{ return m_strName; } //返回节点名
virtual std::list< tNode* >& GetChildBuf(VOID)
{ return m_ChildBuf; } //返回子节点列表
virtual tNode* GetParent(VOID)
{ return m_pParentNode; } //返回父节点
virtual VOID Initial(VOID*) { } //节点初始化
virtual VOID Tick(VOID); //逻辑轮循函数
//查找子节点,如果没有找到,返回NULL;
virtual tNode* LookUpChild(LPCTSTR szNodeName);
virtual VOID AddChild(tNode *pNewNode);//添加子节点到该节点上
//删除某个子节点,当该节点存在时返回TRUE,否则返回FALSE
virtual BOOL EraseChild(tNode* pNode);
virtual VOID EraseAllChild( VOID ); //删除所有子节点
virtual VOID Release(VOID); //释放自己所所拥有的资源
protected:
typedef std::list< tNode * > ChildList;
STRING m_strName;//节点名
ChildList m_ChildBuf;//子节点列表
tNode* m_pParentNode; //父节点指针
friend struct tClass;
WX_DECLARE_DYNAMIC(tNode);
};
tNode类里有一个非常重要的宏WX_DECLARE_DYNAMIC。这个宏,在很多管理类当中都使用了。它与WX_IMPLEMENT_DYNAMIC搭配使用,动态的声明并定义tClass类型的成员对象。
//类定义声明宏
#define WX_DECLARE_DYNAMIC(className) \
public: \
static tClass m_class##className; \
virtual const tClass* GetClass(VOID) const; \
static tNode* __stdcall CreateObject();
c++在宏展开的时候##会作为连接操作。\表示下一行也是宏的展开,只不过为了方便阅读换行的。这下读者应该明白它展开后的样子了。为了直观一些展开WX_DECLARE_DYNAMIC(tNode)。
class tNode
{
public:
static tClass m_classtNode;
virtual const tClass* GetClass(VOID) const;
static tNode* __stdcall CreateObject();
}
这里声明的类于函数在TDNode.cpp一开始便使用WX_IMPLEMENT_DYNAMIC(tNode, NULL)进行了实现。WX_IMPLEMENT_DYNAMIC宏是如下定义的:
//类定义实现宏
#define WX_IMPLEMENT_DYNAMIC(className, baseClass) \
static TCHAR sz##className[] = _T(#className); \
tClass className::m_class##className = \
{ sz##className, sizeof(className), className::CreateObject, baseClass, NULL }; \
const tClass* className::GetClass() const \
{ return &className::m_class##className; } \
tNode* className::CreateObject() \
{ return new className; }
展开WX_IMPLEMENT_DYNAMIC(tNode, NULL);我们得到:
static TCHAR sztNode[]=_T("tNode");
tClass tNode::m_classtNode=
{sztNode,
sizeof(tNode),
tNode::CreateObject,
NULL,
NULL};
const tClass* tNode::GetClass()const
{ return &tNode::m_classtNode;}
tNode* tNode::CreateObject()
{ return new tNode;}
我们返回游戏的执行流程,看一下g_theKernel.ReisgerClass如何注册各种管理器及子系统。我们以
g_theKernel.ReisgerClass(GETCLASS(tNode)); 这句为例。首先,展开GETCLASS宏。
//根据类名取得定义类
#define GETCLASS(className) (&className::m_class##className)
我们得到语句:
g_theKernel.ReisgerClass(&tNode::m_classtNode);
tNode::m_classtNode是我们在tNode类中通过WX_DECLARE_DYNAMIC与WX_IMPLEMENT_DYNAMIC声明并实现的。然后我们看一下ReisgerClass所做的工作:
//将某个类注册到全局类检索表函数
VOID tKernel::ReisgerClass(tClass* pNewClass)
{
TDAssert(pNewClass);
if(m_ClassMap[STRING(pNewClass->szClassName)] != NULL)
{
TDThrow(_T("Multi register class:%s"), pNewClass->szClassName);
}
pNewClass->pNextClass = m_pFirstClass;
m_pFirstClass = pNewClass;
//将新的类加入到类检索表
(m_ClassMap)[pNewClass->szClassName] = pNewClass;
}
它首先检查一下,在类检索表中是否已经存在这个类,如果没有注册过,把这个类链入m_pFirstClass指向的链表开始之处。最后更新类检索表m_ClassMap.
VOID CGameProcedure::InitStaticMemeber(VOID)
{
//初始化随即变量种子
srand( (unsigned)timeGetTime() );
g_theKernel.ReisgerClass(GETCLASS(tNode));// 注册本地类
g_theKernel.ReisgerClass(GETCLASS(CNetManager));//网络管理器
g_theKernel.ReisgerClass(GETCLASS(CWorldManager)); //场景管理器
//物体管理器
g_theKernel.ReisgerClass(GETCLASS(CObjectManager));
g_theKernel.ReisgerClass(GETCLASS(CObject));
g_theKernel.ReisgerClass(GETCLASS(CObject_Surface));
g_theKernel.ReisgerClass(GETCLASS(CObject_Effect));
g_theKernel.ReisgerClass(GETCLASS(CObject_Bullet));
//g_theKernel.ReisgerClass(GETCLASS(CObject_SkillObj));
g_theKernel.ReisgerClass(GETCLASS(CObject_Special));
g_theKernel.ReisgerClass(GETCLASS(CObject_Map));
g_theKernel.ReisgerClass(GETCLASS(CObject_Static));
g_theKernel.ReisgerClass(GETCLASS(CObject_Building));
g_theKernel.ReisgerClass(GETCLASS(CObject_Dynamic));
g_theKernel.ReisgerClass(GETCLASS(CObject_Character));
g_theKernel.ReisgerClass(GETCLASS(CObject_PlayerMySelf));
g_theKernel.ReisgerClass(GETCLASS(CObject_PlayerNPC));
g_theKernel.ReisgerClass(GETCLASS(CObject_PlayerOther));
g_theKernel.ReisgerClass(GETCLASS(CObject_ProjTex));
g_theKernel.ReisgerClass(GETCLASS(CObject_ProjTex_MouseTarget));
g_theKernel.ReisgerClass(GETCLASS(CObject_ProjTex_AuraDure));
g_theKernel.ReisgerClass(GETCLASS(CTripperObject_Transport));
g_theKernel.ReisgerClass(GETCLASS(CTripperObject_ItemBox));
g_theKernel.ReisgerClass(GETCLASS(CTripperObject_Resource));
g_theKernel.ReisgerClass(GETCLASS(CTripperObject_Platform));
g_theKernel.ReisgerClass(GETCLASS(CInputSystem));//输入管理器
g_theKernel.ReisgerClass(GETCLASS(tTimeSystem));//计时器
g_theKernel.ReisgerClass(GETCLASS(CSoundSystemFMod));//声音管理器
g_theKernel.ReisgerClass(GETCLASS(CDataBaseSystem));//数据库管理器
g_theKernel.ReisgerClass(GETCLASS(CVariableSystem));//变量管理器
g_theKernel.ReisgerClass(GETCLASS(CGameInterface));//UI操作接口
g_theKernel.ReisgerClass(GETCLASS(CUIDataPool));//UI数据池
g_theKernel.ReisgerClass(GETCLASS(CDataPool));
g_theKernel.ReisgerClass(GETCLASS(CCursorMng));//UI鼠标操作类
g_theKernel.ReisgerClass(GETCLASS(CScriptSystem));//脚本系统
g_theKernel.ReisgerClass(GETCLASS(CEventSystem));//事件系统
g_theKernel.ReisgerClass(GETCLASS(CActionSystem));//操作管理
g_theKernel.ReisgerClass(GETCLASS(CFakeObjSystem));//UI模型显示管理
g_theKernel.ReisgerClass(GETCLASS(CHelperSystem));//外接帮助系统
...//省略
}
由上面的代码可以看到,g_theKernel是存放游戏核心数据的一个全局变量,它是在Global.cpp中声明的。我们来看一下代码:
#include "StdAfx.h"
#include "Global.h"
tKernel g_theKernel;//数据核心
HWND g_hMainWnd = NULL;//主窗口
HINSTANCE g_hInstance = NULL;//当前主程序模块句柄
const CHAR VERSION_INFO[] = "0.0.0005";//当前版本号
const CHAR GAME_TITLE[] ="武侠世界";//标题
可以看到,除了数据核心之外,还有主窗口句柄、主程序模块句柄、主窗口标题以及版本信息等全局变量。g_theKernel在这声明为tKernel类。
我们先来了解一下tKernel类的成员变量。它定义在TDKernel.h文件中。
protected:
std::map< STRING, tClass* > m_ClassMap;//全局定义类检索表
tClass* m_pFirstClass; //类检索表中第一个类
tNode m_theRoot; //根节点
//插件信息
struct PLUGIN_INFO
{
HMODULE hModule;
STRING strPluginFile;
FUNC_DLLINIT pfnDllInit;
FUNC_DLLRELEASE pfnDllRelease;
};
std::vector< PLUGIN_INFO > m_vAllPlugin;//所有插件
static tKernel* s_pMe;//指向自己的指针
由上面的代码可以看出,tKernel类存放了三种数据,一是全局类的信息,二是插件的信息,三是指向自己的指针。我们重点看一下前两种。由于插件信息的数据结构比较简单,我们先来看一下。PLUGIN_INFO结构中记录了dll句柄,dll文件名,以及dll初始化以及释放的两个函数指针。所有的插件,都以PLUGIN_INFO的结构存放在vector容器之中。
至于全局类信息的存储,利用了tClass和tNode两种类型以及类名到类指针的映射表std::map< STRING, tClass* >。
class tNode
{
public:
tNode(VOID);
tNode(LPCTSTR szName);
virtual ~tNode() { Release(); }
virtual INT GetChildNum(VOID) const
{ return (INT)m_ChildBuf.size(); } //返回子节点数目
virtual const STRING& GetNodeName(VOID) const
{ return m_strName; } //返回节点名
virtual std::list< tNode* >& GetChildBuf(VOID)
{ return m_ChildBuf; } //返回子节点列表
virtual tNode* GetParent(VOID)
{ return m_pParentNode; } //返回父节点
virtual VOID Initial(VOID*) { } //节点初始化
virtual VOID Tick(VOID); //逻辑轮循函数
//查找子节点,如果没有找到,返回NULL;
virtual tNode* LookUpChild(LPCTSTR szNodeName);
virtual VOID AddChild(tNode *pNewNode);//添加子节点到该节点上
//删除某个子节点,当该节点存在时返回TRUE,否则返回FALSE
virtual BOOL EraseChild(tNode* pNode);
virtual VOID EraseAllChild( VOID ); //删除所有子节点
virtual VOID Release(VOID); //释放自己所所拥有的资源
protected:
typedef std::list< tNode * > ChildList;
STRING m_strName;//节点名
ChildList m_ChildBuf;//子节点列表
tNode* m_pParentNode; //父节点指针
friend struct tClass;
WX_DECLARE_DYNAMIC(tNode);
};
tNode类里有一个非常重要的宏WX_DECLARE_DYNAMIC。这个宏,在很多管理类当中都使用了。它与WX_IMPLEMENT_DYNAMIC搭配使用,动态的声明并定义tClass类型的成员对象。
//类定义声明宏
#define WX_DECLARE_DYNAMIC(className) \
public: \
static tClass m_class##className; \
virtual const tClass* GetClass(VOID) const; \
static tNode* __stdcall CreateObject();
c++在宏展开的时候##会作为连接操作。\表示下一行也是宏的展开,只不过为了方便阅读换行的。这下读者应该明白它展开后的样子了。为了直观一些展开WX_DECLARE_DYNAMIC(tNode)。
class tNode
{
public:
static tClass m_classtNode;
virtual const tClass* GetClass(VOID) const;
static tNode* __stdcall CreateObject();
}
这里声明的类于函数在TDNode.cpp一开始便使用WX_IMPLEMENT_DYNAMIC(tNode, NULL)进行了实现。WX_IMPLEMENT_DYNAMIC宏是如下定义的:
//类定义实现宏
#define WX_IMPLEMENT_DYNAMIC(className, baseClass) \
static TCHAR sz##className[] = _T(#className); \
tClass className::m_class##className = \
{ sz##className, sizeof(className), className::CreateObject, baseClass, NULL }; \
const tClass* className::GetClass() const \
{ return &className::m_class##className; } \
tNode* className::CreateObject() \
{ return new className; }
展开WX_IMPLEMENT_DYNAMIC(tNode, NULL);我们得到:
static TCHAR sztNode[]=_T("tNode");
tClass tNode::m_classtNode=
{sztNode,
sizeof(tNode),
tNode::CreateObject,
NULL,
NULL};
const tClass* tNode::GetClass()const
{ return &tNode::m_classtNode;}
tNode* tNode::CreateObject()
{ return new tNode;}
我们返回游戏的执行流程,看一下g_theKernel.ReisgerClass如何注册各种管理器及子系统。我们以
g_theKernel.ReisgerClass(GETCLASS(tNode)); 这句为例。首先,展开GETCLASS宏。
//根据类名取得定义类
#define GETCLASS(className) (&className::m_class##className)
我们得到语句:
g_theKernel.ReisgerClass(&tNode::m_classtNode);
tNode::m_classtNode是我们在tNode类中通过WX_DECLARE_DYNAMIC与WX_IMPLEMENT_DYNAMIC声明并实现的。然后我们看一下ReisgerClass所做的工作:
//将某个类注册到全局类检索表函数
VOID tKernel::ReisgerClass(tClass* pNewClass)
{
TDAssert(pNewClass);
if(m_ClassMap[STRING(pNewClass->szClassName)] != NULL)
{
TDThrow(_T("Multi register class:%s"), pNewClass->szClassName);
}
pNewClass->pNextClass = m_pFirstClass;
m_pFirstClass = pNewClass;
//将新的类加入到类检索表
(m_ClassMap)[pNewClass->szClassName] = pNewClass;
}
它首先检查一下,在类检索表中是否已经存在这个类,如果没有注册过,把这个类链入m_pFirstClass指向的链表开始之处。最后更新类检索表m_ClassMap.