// object.h
#include <boost/function.hpp>
#include <boost/bind.hpp>
#include <map>
#include <string>
class FObject
{
public:
typedef boost::function<void()> EventFunction;
struct EventParam
{
std::string strEvent;
EventFunction eventFunc;
float fDeltaTime;
mutable float CurrentTime;
bool bLoop;
};
typedef std::map<std::string, EventParam> EventMap;
public:
virtual ~FObject();
virtual void Tick( float fDeltaTime );
public:
void ScheduleEvent( const std::string& strEvent, float fDeltaTime, bool bLoop, EventFunction EventFunc );
bool IsEventActive( const std::string& strEvent ) const;
void KillEvent( const std::string& strEvent );
#define SCHEDULE_EVENT( DeltaTime, bLoop, nameFunc ) \
ScheduleEvent( #nameFunc, DeltaTime, bLoop, boost::bind( nameFunc, this ) )
#define SCHEDULE_KILL( nameFunc ) \
KillEvent( #nameFunc )
private:
EventMap m_Events;
};
// object.cpp
#include "Object.h"
FObject::~FObject()
{
}
void FObject::Tick( float fDeltaTime )
{
for( EventMap::iterator it = m_Events.begin();
it != m_Events.end();
)
{
it->second.CurrentTime -= fDeltaTime;
if( it->second.CurrentTime <= 0.0f )
{
if( it->second.eventFunc )
{
it->second.eventFunc();
}
if( !it->second.bLoop )
{
it = m_Events.erase(it);
}
else
{
it->second.CurrentTime = it->second.fDeltaTime;
++it; // this is very important
}
}
else
{
++it; // this is very important
}
}
}
void FObject::ScheduleEvent( const std::string& strEvent, float fDeltaTime, bool bLoop, EventFunction EventFunc )
{
EventParam Param;
Param.strEvent = strEvent;
Param.fDeltaTime = fDeltaTime;
Param.CurrentTime = fDeltaTime;
Param.eventFunc = EventFunc;
Param.bLoop = bLoop;
EventMap::iterator itPos = m_Events.find( strEvent );
if( itPos != m_Events.end() )
{
itPos->second = Param;
}
else
{
m_Events.insert( std::make_pair( strEvent, Param ) );
}
}
bool FObject::IsEventActive( const std::string& strEvent ) const
{
return m_Events.find( strEvent ) != m_Events.end();
}
void FObject::KillEvent( const std::string& strEvent )
{
EventMap::iterator itPos = m_Events.find( strEvent );
if( itPos != m_Events.end() )
{
m_Events.erase(itPos);
}
}
// 够简单吧,这个只是把函数对象保存下来的办法。通常只应该用在本Object身上,这样当本Object失效之后所有的延迟调用都会失效。缺陷就是每个Object都需要被tick才可以支持。可选的方案还可以创建一个用于统一管理的ScheduleManager,这样只需要tick manager就可以了,这个方案的缺陷可能会调用到已经不存在的Object的方法导致崩溃。
这个姑且如此,能用了。先就这样,有问题再说。嘿嘿。