现在的位置: 首页 > 综合 > 正文

武侠世界客户端源代码【静态变量的初始化之二】

2013年03月14日 ⁄ 综合 ⁄ 共 5622字 ⁄ 字号 评论关闭

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;
}

抱歉!评论已关闭.