1.首先在c++源码中添加需要注册到Lua的函数
INT LuaFnSetTimer(Lua_State* L) { LUA_ENTER_FUNCTION SceneID_t sceneId = Lua_ValueToNumber(L,1); ObjID_t selfId = Lua_ValueToNumber(L,2); ScriptID_t scriptId = Lua_ValueToNumber(L,3); const CHAR* funcName = Lua_ValueToString(L,4); INT tickTime = Lua_ValueToNumber(L,5); BEGINHUMANDEFINE(“LuaFnSetTimer”) if(pHuman->GetUseTimerCount() < pHuman->GetMaxTimerCount()) { INT sceneTimerIndex = pScene->GetSceneTimer()->GetTimer(); AssertEx(sceneTimerIndex>=0 && sceneTimerIndex < g_Config.m_ConfigInfo.m_MaxTimerCount,”No Timer resource for allocate”); if(sceneTimerIndex>=0 && sceneTimerIndex < g_Config.m_ConfigInfo.m_MaxTimerCount) { pHuman->AddTimer(sceneTimerIndex); pScene->GetSceneTimer()->StartTheTimer(sceneTimerIndex,selfId,scriptId,funcName,tickTime); Lua_PushNumber(L,sceneTimerIndex); return 1; } } ENDHUMANDEFINE RETURNFALSE LUA_LEAVE_FUNCTION RETURNFALSE }
2.然后将函数注册进Lua中
// 定义Lua注册通用的函数指针 typedef INT (*FuncProto)(Lua_State * L); // 定义工具结构 struct _Str2Func { CHAR* funcname; FuncProto proto; }; // 像这样定义中间结构 struct _Str2Func functbl[] = { {“AddEventList”,FuncProto(LuaFnAddNumText)}, {“GetMission”, FuncProto(LuaFnGetMission)}, {“CityMoveTo”, FuncProto(LuaFnCityMoveTo)}, }; } // 像这样进行 使用FireFox的Lua引擎进行 函数注册 for(INT i=0; i<sizeof(LuaFnTbl::functbl)/sizeof(_Str2Func); i++) { mLua.RegisterFunction(LuaFnTbl::functbl[i].funcname,(VOID*)(LuaFnTbl::functbl[i].proto)); }
3.开始使用定时器
// 然后脚本设置一个定时器 5个参数见函数定义 需要传人函数名 LuaFnSetTimer(1,2,3,4,5);
4.定时器实现
// 调用服务器中的定时器 以下是定义
class CMyTimer { private: UINT m_uTickTerm; UINT m_uTickOld; public: BOOL m_bOper; public: CMyTimer() { CleanUp() ; } BOOL IsSetTimer( ){ return m_bOper ; } VOID SetTermTime( UINT uTerm ){ m_uTickTerm =uTerm; } UINT GetTermTime( ){ return m_uTickTerm ; } UINT GetTickOldTime( ){ return m_uTickOld; } VOID CleanUp( ) { m_uTickTerm = 0 ; m_bOper = FALSE ; m_uTickOld = 0 ; } VOID BeginTimer(UINT uTerm, UINT uNow) { m_bOper = TRUE; m_uTickTerm =uTerm; m_uTickOld =uNow; } BOOL CountingTimer(UINT uNow) { if(!m_bOper) return FALSE; UINT uNew =uNow; if(uNew<m_uTickOld+m_uTickTerm ) return FALSE; m_uTickOld =uNew; return TRUE; } UINT GetLeaveTime(UINT uNow)//剩余时间; { if(!CountingTimer(uNow)) { return m_uTickTerm+m_uTickOld-uNow; } return 0; } }; // 场景定时器 ================= class SceneTimer { public: CMyTimer mRefeshTimer; #define FuncNameLen 32 typedef struct _MyTimers { CHAR scriptFuncName[FuncNameLen]; INT selfId; INT scriptId; CMyTimer timer; }MyTimer; MyTimer* m_pTimers; MyTimer* head; INT index; INT maxCount; Scene* m_pScene; //仅测试 #if _DEBUG INT m_currentUse; #endif SceneTimer(); ~SceneTimer(); VOID CleanUp() ; BOOL IsInit() { if( m_pScene==NULL ) return FALSE ; else return TRUE ; }; VOID CreateTimer(INT maxCount,Scene* pScene); VOID InitOne(INT i); INT GetTimer(); VOID StartTheTimer(INT sceneTimerIndex,INT selfId,INT scriptId,const CHAR* funcName,INT tickTime); VOID FreeTimer(INT index); BOOL CheckTimer(INT index); VOID OnTimer(UINT uTime); Scene* GetScene() { return m_pScene; } }; //每个场景有一个线程来做处理 *备注 每个:”=====->” 都表示进入下一个函数调用 // 以下给出调用过程 VOID SceneThread::run( )===== -> BOOL ret = m_apScene[i]->Tick( ) ; =====-> ret = HeartBeat( ) ;===== -> m_pSceneTimers->OnTimer(uTime);->检查定时器是否触发<-=====–> GetScene()->GetLuaInterface()->ExeScript_DDDD( m_pTimers[i].scriptId, m_pTimers[i].scriptFuncName, (INT)GetScene()->SceneID(), (INT)m_pTimers[i].selfId, (INT)i, (INT)0 ) ; =====->
1.依据数据组装出函数名
2.return ExeFile_DDDD(filename,funcnameX,Param0,Param1,Param2,Param3,bLoad);=====->
bRet = mLua.CallFunction( funcname, 1, “dddd”, Param0, Param1, Param2, Param3 ) ;
到这里一个定时器就过程就算完成