VOID CGameProcedure::InitStaticMemeber(VOID) { ...//省略
// 加载插件中的类 //g_theKernel.LoadPlugin(_T("Debuger.dll"), &g_theKernel); g_theKernel.LoadPlugin(_T("WXRender.dll"), &g_theKernel); g_theKernel.LoadPlugin(_T("UISystem.dll"), &g_theKernel); //初始化所有的循环实例 s_pProcLogIn = new CGamePro_Login(); //登录循环 s_pProcCharSel = new CGamePro_CharSel(); //人物选择流程 s_pProcCharCreate = new CGamePro_CharCreate(); // 人物创建流程 s_pProcEnter = new CGamePro_Enter(); //等待进入场景流程 s_pProcMain = new CGamePro_Main(); //主游戏循环 s_pProcChangeScene = new CGamePro_ChangeScene(); //服务器切换流程
// 初始化数据核心 //0. 输入管理器 s_pInputSystem = (tInputSystem*) g_theKernel.NewNode(_T("CInputSystem"), _T("bin"), _T("input")); //1. 计时器 s_pTimeSystem = (tTimeSystem*) g_theKernel.NewNode(_T("tTimeSystem"), _T("bin"), _T("time")); //2. 网络管理器 s_pNetManager = (CNetManager*) g_theKernel.NewNode(_T("CNetManager"), _T("bin"), _T("netman")); //3. 音效管理器 s_pSoundSystem = (tSoundSystem*) g_theKernel.NewNode(_T("CSoundSystemFMod"), _T("bin"), _T("snd")); //4. 渲染器节点 s_pGfxSystem = (CRenderSystem*) g_theKernel.NewNode(_T("CRenderSystem"), _T("bin"), _T("gfx")); //5. 调试器节点 // s_pDebuger = (tDebuger*) g_theKernel.NewNode(_T("TDDebuger"), _T("bin"), _T("debuger")); //6. 物体管理器 s_pObjectManager= (tObjectSystem*) g_theKernel.NewNode(_T("CObjectManager"), _T("bin"), _T("objman")); //7. UI管理器 s_pUISystem = (tUISystem*) g_theKernel.NewNode(_T("CUISystem"), _T("bin"), _T("ui_")); //8. 世界管理器 s_pWorldManager = (tWorldSystem*) g_theKernel.NewNode(_T("CWorldManager"), _T("bin"), _T("worldman")); //9. 数据库管理器 s_pDataBaseSystem = (tDataBaseSystem*) g_theKernel.NewNode(_T("CDataBaseSystem"), _T("bin"), _T("dbc")); //10. 系统变量管理器 s_pVariableSystem = (tVariableSystem*) g_theKernel.NewNode(_T("CVariableSystem"), _T("bin"), _T("var")); //11. 接口管理器 s_pGameInterface = ( tGameInterfaceBase* ) g_theKernel.NewNode( _T("CGameInterface"), _T("bin"), _T("interface")); //12. UI数据池 s_pDataPool = ( tDataPool* ) g_theKernel.NewNode( _T( "CUIDataPool" ), _T( "bin" ), _T( "datapool" ) ); s_pDataPool_ = ( tDataPool_* ) g_theKernel.NewNode( _T( "CDataPool" ), _T( "bin" ), _T( "datapool_" ) ); //13. 鼠标指针管理器 s_pCursorMng = ( tCursorSystem* ) g_theKernel.NewNode( _T( "CCursorMng"), _T( "bin" ), _T("cursor" ) ); //14. 脚本系统 s_pScriptSystem = ( tScriptSystem* ) g_theKernel.NewNode( _T( "CScriptSystem"), _T( "bin" ), _T("script" ) ); //15. 事件系统 s_pEventSystem = ( tEventSystem* ) g_theKernel.NewNode( _T( "CEventSystem"), _T( "bin" ), _T("event" ) );
//16. 操作管理 s_pActionSystem = ( tActionSystem* ) g_theKernel.NewNode( _T( "CActionSystem"), _T( "bin" ), _T("action" ) ); //17. UI模型显示管理 s_pFakeObjSystem = ( tFakeObjSystem* ) g_theKernel.NewNode( _T( "CFakeObjSystem"), _T( "bin" ), _T("fake" ) ); //18. 外接帮助系统 s_pHelperSystem = ( tHelperSystem* ) g_theKernel.NewNode( _T( "CHelperSystem"), _T( "bin" ), _T("helper" ) ); //19. 资源提供 s_pResourceProvider = ( CResourceProvider* ) g_theKernel.NewNode( _T( "CResourceProvider"), _T( "bin" ), _T("resprovider" ) );
...//省略
|
CGameProcedure::InitStaticMemeber这一部分代码做了三件事情
1. 加载插件并检查其合法性
2. 创建并初始化游戏的各个过程类实例
3. 初始化数据核心
插件的加载就是载入dll并检查是不是合法的插件。代码很容易懂,就不看了。过程类实例的初始化等到按游戏的运行独到相应的过程时再看。这儿我们主要看看数据核心的初始化。
数据核心的初始化是创建一棵类树。g_theKernel.NewNode的主要在作用以root节点为根的树中的指定位置添加新的节点。它是怎么样创建类节点的呢?
在上一篇中,我们看到了,各个类已经注册在类检索表中了。我们可以通过类检索表可以方便的得到对应类的创建函数CreateObject(LPCTSTR szName)。这里有个小技巧,CreateObject只在TClass类中实现了,为什么可以创建不同类的节点呢? TClass只是各类的一个注册接口,我们先来看看它的结构
struct /*TDENGDA_API*/ tClass { LPCTST szClassName; // Node类名称 INT nObjectSize; //Node类的大小 tNode* (__stdcall* pfnCreateObject)(); // 函数指针,用于生成一个Node类实例 tClass* pBaseClass; //所继承的基类 tClass* pNextClass; //下一个类 tNode* CreateObject(LPCTSTR szName); //用于生成一个实例的函数
};
|
我们可以看到,它有一个函数指针。在定义各个节点类的时候,这个指针设为每个类的创建函数。(节点类的tClass类实例是通过WX_DECLARE_DYNAMIC,WX_DECLARE_DYNAMIC来声明和实现的)CreateObject是通过这些函数指针实现的统一创建接口。
下面研究g_theKernel.NewNode的代码,这个函数实现了重载。一个是根据字符串形式的路径来创建新节点,另一个根据父节点来创建新节点。两个的过程差不多,找到位置后,都调用CreateObject创建节点。
//根据字符串形式的路径来创建新节点 tNode* tKernel::NewNode(LPCTSTR szClassName, LPCTSTR szPosition, LPCTSTR szNodeName) { TDAssert(szClassName && szPosition && szNodeName);
//打开类
tClass *pClass = OpenClass(szClassName); if(!pClass) { TDThrow(_T("(tKernel::NewNode)Can't create new Node[%s]"), szClassName); } std::vector< STRING > vPathSplitBuf; TDU_ConvertStringToVector(szPosition, vPathSplitBuf, _T("\\/"));
tNode *pCurrentNode = &m_theRoot; tNode *pFindNode = NULL;
//搜索父节点
for(register INT i=0; i<(INT)vPathSplitBuf.size(); i++) { tNode *pFindNode = pCurrentNode->LookUpChild((LPCTSTR)vPathSplitBuf[i].c_str()); if(pFindNode == NULL) { tNode *pNewNode = new tNode(vPathSplitBuf[i].c_str()); pCurrentNode->AddChild(pNewNode); pFindNode = pNewNode; } pCurrentNode = pFindNode; } //查找是否该节点已经存在 if(pCurrentNode->LookUpChild(szNodeName)) { TDThrow(_T("(tKernel::NewNode)The Node[%s] has exist!"), szNodeName); } tNode *pNewNode = (tNode *)pClass->CreateObject(szNodeName); pCurrentNode->AddChild(pNewNode); return pNewNode; }
|
这函数先调用OpenClass打开类,所谓的打开类,就是在类检索表中查到指定类的TClass指针。然后通过TDU_ConvertStringToVector把路径按照"\"或者"/"切分开,每一项都是要建节点的一个父节点。然后在循环中,依次检查父节点是否存在,不存在就创建。最后以路径中最后一个节点为父节点,先查看子节点中是否存在要新建的节点,不存在的话,就新建。
根据父节点创建比这个要更简单。由于父节点是以参数形式传入的,所以我们直接检查一下它的子节点中是否存在要建节点,不存在,创建就完事了。
tNode* tKernel::NewNode(LPCTSTR szClassName, tNode* pParentNode, LPCTSTR szNodeName) { TDAssert(szClassName && pParentNode && szNodeName); //打开类 tClass *pClass = OpenClass(szClassName); if(!pClass) { TDThrow(_T("(tKernel::NewNode)Can't create new Node[%s]"), szClassName); } //查找是否该节点已经存在 if(pParentNode->LookUpChild(szNodeName)) { TDThrow(_T("(tKernel::NewNode)The Node[%s] has exist!"), szNodeName); } tNode *pNewNode = (tNode *)pClass->CreateObject(szNodeName); pParentNode->AddChild(pNewNode); return pNewNode; }
|