武侠-event

一 武侠的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 ;
    }
};

 

 

变量

 //通过事件名称检索表
 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 ;
}
//  注册事件处理函数
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 );
}
 
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 );
    }
}
 

 

             //  距离发生改变,产生事件
            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);
        }
    }
}

 

 

另外有一个回调函数,执行具体的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);
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值