一 武侠的event是个比较强的系统,个人感觉也是做的比较好的,结合lua使用起来很不错
二 实现
1 定义结构
struct
EVENT_DEFINE
{
typedef std::list < std::pair < FUNC_EVENT_HANDLE, UINT > > REGISTER_STRUCT;
GAME_EVENT_ID idEvent;
LPCTSTR szEvent;
BOOL delayProcess;
REGISTER_STRUCT listFuncNotify;
};
struct EVENT
{
EVENT_DEFINE * pEventDef;
std::vector < STRING > vArg;
bool operator == ( const EVENT & other)
{
if (other.pEventDef != pEventDef)
return false ;
if (other.vArg.size() != vArg.size())
return false ;
for (register size_t i = 0 ; i < vArg.size(); i ++ )
{
if (vArg[i] != other.vArg[i])
return false ;
}
return true ;
}
};
{
typedef std::list < std::pair < FUNC_EVENT_HANDLE, UINT > > REGISTER_STRUCT;
GAME_EVENT_ID idEvent;
LPCTSTR szEvent;
BOOL delayProcess;
REGISTER_STRUCT listFuncNotify;
};
struct EVENT
{
EVENT_DEFINE * pEventDef;
std::vector < STRING > vArg;
bool operator == ( const EVENT & other)
{
if (other.pEventDef != pEventDef)
return false ;
if (other.vArg.size() != vArg.size())
return false ;
for (register size_t i = 0 ; i < vArg.size(); i ++ )
{
if (vArg[i] != other.vArg[i])
return false ;
}
return true ;
}
};
变量
//通过事件名称检索表
std::map< STRING, EVENT_DEFINE* > m_mapEventIndex_AsName;
//通过事件ID检索表
std::map< GAME_EVENT_ID, EVENT_DEFINE* > m_mapEventIndex_AsID;
保存了所有注册的事件,可以通过ID和Name索引
//事件队列
std::list< EVENT > m_queueEvent;
//慢速处理队列, 每桢一个,防止过多的消息同时涌现
std::list< EVENT > m_delayQueueEvent;
保存了当前需要处理的事件
2 lua注册接口
INT CUIWindowItem::LUA_RegisterEvent(LuaPlus::LuaState
*
pState)
{
LuaStack args(pState);
if ( ! (args[ 2 ].IsString()))
return 0 ;
if (m_bLayoutLoaded)
{
KLThrow( " %s Must register event in \"***PreLoad\" Function " , m_strWindowName.c_str());
}
STRING strEventName = args[ 2 ].GetString();
g_pEventSys -> RegisterEventHandle(strEventName, _OnGameEvent, (DWORD)(DWORD_PTR) this );
return 0 ;
}
{
LuaStack args(pState);
if ( ! (args[ 2 ].IsString()))
return 0 ;
if (m_bLayoutLoaded)
{
KLThrow( " %s Must register event in \"***PreLoad\" Function " , m_strWindowName.c_str());
}
STRING strEventName = args[ 2 ].GetString();
g_pEventSys -> RegisterEventHandle(strEventName, _OnGameEvent, (DWORD)(DWORD_PTR) this );
return 0 ;
}
//
注册事件处理函数
VOID CEventSystem::RegisterEventHandle( const STRING & nameEvent, FUNC_EVENT_HANDLE funHandle, UINT uOwnerData)
{
if ( ! funHandle)
return ;
EVENT_DEFINE * pEvent = m_mapEventIndex_AsName[nameEvent];
if ( ! pEvent)
return ;
pEvent -> listFuncNotify.push_back( std::make_pair(funHandle, uOwnerData) );
}
VOID CEventSystem::RegisterEventHandle( const STRING & nameEvent, FUNC_EVENT_HANDLE funHandle, UINT uOwnerData)
{
if ( ! funHandle)
return ;
EVENT_DEFINE * pEvent = m_mapEventIndex_AsName[nameEvent];
if ( ! pEvent)
return ;
pEvent -> listFuncNotify.push_back( std::make_pair(funHandle, uOwnerData) );
}
3 添加处理事件
VOID CEventSystem::PushEvent(STRING
&
eventName, LPCTSTR szArg0, LPCTSTR szArg1, INT iArg2, INT iArg3)
{
if (m_mapEventIndex_AsName.find(eventName) == m_mapEventIndex_AsName.end()) return ;
EVENT event ;
event .pEventDef = m_mapEventIndex_AsName[eventName];
event .vArg.push_back(szArg0);
event .vArg.push_back(szArg1);
CHAR szTemp[ 32 ];
_snprintf(szTemp, 32 , " %d " , iArg2);
event .vArg.push_back(szTemp);
_snprintf(szTemp, 32 , " %d " , iArg3);
event .vArg.push_back(szTemp);
_PushEvent( event );
}
{
if (m_mapEventIndex_AsName.find(eventName) == m_mapEventIndex_AsName.end()) return ;
EVENT event ;
event .pEventDef = m_mapEventIndex_AsName[eventName];
event .vArg.push_back(szArg0);
event .vArg.push_back(szArg1);
CHAR szTemp[ 32 ];
_snprintf(szTemp, 32 , " %d " , iArg2);
event .vArg.push_back(szTemp);
_snprintf(szTemp, 32 , " %d " , iArg3);
event .vArg.push_back(szTemp);
_PushEvent( event );
}
void
CEventSystem::_PushEvent(
const
EVENT
&
event
)
{
if ( ! event .pEventDef)
return ;
// 如果是慢速处理的事件
if ( event .pEventDef -> delayProcess)
{
m_delayQueueEvent.push_back( event );
}
else
{
m_queueEvent.push_back( event );
}
}
{
if ( ! event .pEventDef)
return ;
// 如果是慢速处理的事件
if ( event .pEventDef -> delayProcess)
{
m_delayQueueEvent.push_back( event );
}
else
{
m_queueEvent.push_back( event );
}
}
//
距离发生改变,产生事件
std::vector < STRING > vParam;
CHAR szTemp[MAX_PATH];
_snprintf(szTemp, MAX_PATH, " %d " , pObject -> GetID());
vParam.push_back(szTemp);
vParam.push_back( " distance " );
_snprintf(szTemp, MAX_PATH, " %.3f " , fDistance);
vParam.push_back(szTemp);
CEventSystem::GetMe() -> PushEvent(GE_OBJECT_CARED_EVENT, vParam);
std::vector < STRING > vParam;
CHAR szTemp[MAX_PATH];
_snprintf(szTemp, MAX_PATH, " %d " , pObject -> GetID());
vParam.push_back(szTemp);
vParam.push_back( " distance " );
_snprintf(szTemp, MAX_PATH, " %.3f " , fDistance);
vParam.push_back(szTemp);
CEventSystem::GetMe() -> PushEvent(GE_OBJECT_CARED_EVENT, vParam);
4 执行事件
VOID CEventSystem::ProcessAllEvent(VOID)
{
// 处理慢速队列
if ( ! (m_delayQueueEvent.empty()))
{
const UINT WORK_STEP = 2 ;
UINT nTickCountNow = CGameProcedure::s_pTimeSystem -> GetTickCount();
UINT nTickCountStep = CGameProcedure::s_pTimeSystem -> CalSubTime(m_dwLastTickCount, nTickCountNow);
if (nTickCountStep >= WORK_STEP)
{
m_dwLastTickCount = nTickCountNow;
const EVENT & event = * (m_delayQueueEvent.begin());
_ProcessEvent( event );
m_delayQueueEvent.erase(m_delayQueueEvent.begin());
}
}
register std::list < EVENT > ::iterator it;
for (it = m_queueEvent.begin(); it != m_queueEvent.end(); it ++ )
{
const EVENT & event = * it;
// 检测是否有同样的Event已经被处理
bool bMultiPushed = false ;
for (register std::list < EVENT > ::iterator itPrev = m_queueEvent.begin(); itPrev != it; itPrev ++ )
{
if ( * itPrev == * it)
{
bMultiPushed = true ;
break ;
}
}
if (bMultiPushed)
continue ;
_ProcessEvent( event );
}
m_queueEvent.clear();
}
void CEventSystem::_ProcessEvent( const EVENT & event )
{
// 查找事件定义
EVENT_DEFINE * pEventDef = event .pEventDef;
if ( ! pEventDef)
return ;
// 调用处理函数
if ( ! (pEventDef -> listFuncNotify.empty()))
{
EVENT_DEFINE::REGISTER_STRUCT::iterator it;
for (it = pEventDef -> listFuncNotify.begin(); it != pEventDef -> listFuncNotify.end(); it ++ )
{
if (( * it).first)
(( * it).first)( & event , ( * it).second);
}
}
}
{
// 处理慢速队列
if ( ! (m_delayQueueEvent.empty()))
{
const UINT WORK_STEP = 2 ;
UINT nTickCountNow = CGameProcedure::s_pTimeSystem -> GetTickCount();
UINT nTickCountStep = CGameProcedure::s_pTimeSystem -> CalSubTime(m_dwLastTickCount, nTickCountNow);
if (nTickCountStep >= WORK_STEP)
{
m_dwLastTickCount = nTickCountNow;
const EVENT & event = * (m_delayQueueEvent.begin());
_ProcessEvent( event );
m_delayQueueEvent.erase(m_delayQueueEvent.begin());
}
}
register std::list < EVENT > ::iterator it;
for (it = m_queueEvent.begin(); it != m_queueEvent.end(); it ++ )
{
const EVENT & event = * it;
// 检测是否有同样的Event已经被处理
bool bMultiPushed = false ;
for (register std::list < EVENT > ::iterator itPrev = m_queueEvent.begin(); itPrev != it; itPrev ++ )
{
if ( * itPrev == * it)
{
bMultiPushed = true ;
break ;
}
}
if (bMultiPushed)
continue ;
_ProcessEvent( event );
}
m_queueEvent.clear();
}
void CEventSystem::_ProcessEvent( const EVENT & event )
{
// 查找事件定义
EVENT_DEFINE * pEventDef = event .pEventDef;
if ( ! pEventDef)
return ;
// 调用处理函数
if ( ! (pEventDef -> listFuncNotify.empty()))
{
EVENT_DEFINE::REGISTER_STRUCT::iterator it;
for (it = pEventDef -> listFuncNotify.begin(); it != pEventDef -> listFuncNotify.end(); it ++ )
{
if (( * it).first)
(( * it).first)( & event , ( * it).second);
}
}
}
另外有一个回调函数,执行具体的lua调用
VOID WINAPI CUIWindowItem::_OnGameEvent(
const
EVENT
*
pEvent, UINT dwOwnerData)
{
KLAssert(pEvent);
// --------------------------------------------------------
// 分发
CUIWindowItem * pWinItem = (CUIWindowItem * )(DWORD_PTR)(dwOwnerData);
if ( ! pWinItem)
return ;
// 加载
if ( ! (pWinItem -> m_bLayoutLoaded))
{
pWinItem -> LoadWindow();
}
// --------------------------------------------------------
// 参数
for (INT i = 0 ; i < (INT)pEvent -> vArg.size(); i ++ )
{
CHAR szTemp[MAX_PATH];
_snprintf(szTemp, MAX_PATH, " arg%d " , i);
g_pScriptSys -> GetLuaState() -> GetGlobals().SetString(szTemp, pEvent -> vArg[i].c_str());
}
// --------------------------------------------------------
// 调用脚本
CHAR szFunctionName[MAX_PATH];
_snprintf(szFunctionName, MAX_PATH, " %s_OnEvent " , pWinItem -> m_strWindowName.c_str());
CHAR szFunctionParam[MAX_PATH];
_snprintf(szFunctionParam, MAX_PATH, " \"%s\" " , pEvent -> pEventDef -> szEvent);
pWinItem -> m_pScriptEnv -> DoFunction(szFunctionName, szFunctionParam);
}
{
KLAssert(pEvent);
// --------------------------------------------------------
// 分发
CUIWindowItem * pWinItem = (CUIWindowItem * )(DWORD_PTR)(dwOwnerData);
if ( ! pWinItem)
return ;
// 加载
if ( ! (pWinItem -> m_bLayoutLoaded))
{
pWinItem -> LoadWindow();
}
// --------------------------------------------------------
// 参数
for (INT i = 0 ; i < (INT)pEvent -> vArg.size(); i ++ )
{
CHAR szTemp[MAX_PATH];
_snprintf(szTemp, MAX_PATH, " arg%d " , i);
g_pScriptSys -> GetLuaState() -> GetGlobals().SetString(szTemp, pEvent -> vArg[i].c_str());
}
// --------------------------------------------------------
// 调用脚本
CHAR szFunctionName[MAX_PATH];
_snprintf(szFunctionName, MAX_PATH, " %s_OnEvent " , pWinItem -> m_strWindowName.c_str());
CHAR szFunctionParam[MAX_PATH];
_snprintf(szFunctionParam, MAX_PATH, " \"%s\" " , pEvent -> pEventDef -> szEvent);
pWinItem -> m_pScriptEnv -> DoFunction(szFunctionName, szFunctionParam);
}