Action,每种状态下的具体操作,eOnEntry,进入改装态时执行一次; eDo, 处于在该状态时便一直执行; eOnExit, 推出状态时执行一次; eOnEvent, 当该状态接收到某一事件时执行一次, 如果接受到某一事件开始需要执行一连串的动作, 则应考虑状态的转移;
State, 状态,每种状态维护 1--输入事件和回调函数的映射关系,2--输入事件和状态转移的关系;
Transition, 就是转移表的元素,输入事件与下一个状态的映射;
StateMachine,状态机,接受输入事件,内部决定是执行相应操作还是进行转台转移;
#pragma once
template<typename T>
class Action
{
typedef void (T::*ActionFunc)();
public:
Action():m_iId(0),m_iEventId(0),m_iMaxEventNum(6),m_pFunc(NULL)
{
}
Action(int id, int iEventId, ActionFunc pFunc):
m_iId(id),
m_iEventId(iEventId),
m_iMaxEventNum(6),
m_pFunc(pFunc)
{
}
virtual ~Action()
{
}
void SetId(int iId) { m_iId = iId; }
int GetId() const { return m_iId; }
void SetType(int iType) { m_iType = iType; }
int GetType() const { return m_iType; }
void SetEventId(int iEventId) { m_iEventId = iEventId; }
int GetEventId() const { return m_iEventId; }
void SetActionFunc(ActionFunc pActionFunc) { m_pFunc = pActionFunc; }
ActionFunc GetActionFunc() const { return m_pFunc; }
void Execute(T* pt)
{
if(m_pFunc!=NULL)
{
(pt->*m_pFunc)();
}
}
enum eWhen
{
eOnEntry = 0, // Action taken on entering the state
eDo, // Action taken during entering the state until leaving the state
eOnExit, // Action taken on leaving the state
eOnEvent // Action taken based on the event received
// - Specify Event, Arguments, and Condition
};
enum eType
{
eAction = 0,
eSendEvent
};
private:
int m_iId;
int m_iType;
int m_iEventId; // the event trigger this action
int m_iMaxEventNum;
ActionFunc m_pFunc;
};
#pragma once
class Transition
{
public:
void SetEventId(int iEventId) { m_iEventId = iEventId; }
int GetEventId() const { return m_iEventId; }
void SetNextStateId(int iNextStateId) { m_iNextStateId = iNextStateId; }
int GetNextStateId() const { return m_iNextStateId; }
private:
int m_iEventId;
int m_iNextStateId;
};
#pragma once
#include <map>
#include "State.h"
#include "Action.h"
#include "Transition.h"
template<typename T>
class State
{
typedef void (T::*ActionFunc)();
typedef std::map<int, Transition*> TransitionMap;
typedef std::map<int, Action<T>*> ActionMap;
public:
State(T* pInstance) { m_pInstance = pInstance; }
virtual ~State(){ m_pInstance=NULL; }
public:
virtual bool Enter( int iEvent = 0 );
virtual bool DoOnce( int iEvent );
virtual void Run();
virtual int Exit( int iEvent );
//
void AddTransition (int iEventId, int iStateId);
void AddAction (int when, int type, int id, ActionFunc funcPtr); // Set default action
void AddAction (int when, int type, int id, int Eventid, ActionFunc funcPtr); // Set OnEvent action
void SetId(int iId) { m_iId = iId; }
int GetId() const { return m_iId; }
void SetInstance(T* pInstance) { m_pInstance = pInstance; }
T* GetInstance() const { return m_pInstance; }
int GetEventNum() const { return m_iEventNum; }
int GetMaxEventNum() const { return m_iMaxEventNum; }
int GetTransitionNum() const;//
private:
T* m_pInstance;
int m_iId;
int m_iEventNum; // 事件数
int m_iMaxEventNum;
ActionMap m_mapActions; // 操作列表,key-- enter,do,exit,event
TransitionMap m_mapTransitions; // 转移函数表,key--EventId
};
template<typename T>
bool State<T>::Enter( int iEvent )
{
if (m_mapActions.size() > 2)// 0,1,2为固定事件
{
ActionMap::iterator iter = m_mapActions.find(Action<T>::eOnEvent);
for(iter;iter!=m_mapActions.end();++iter)
{
Action<T>* pAction = iter->second;
if(pAction->GetEventId()==iEvent)
{
pAction->Execute(m_pInstance);
}
}
}
ActionMap::iterator iter = m_mapActions.find(Action<T>::eOnEntry);
if(iter!=m_mapActions.end())
{
Action<T>* pAction = iter->second;
if(pAction) pAction->Execute(m_pInstance);
}
return true;
}
template<typename T>
void State<T>::Run()
{
ActionMap::iterator iter = m_mapActions.find(Action<T>::eDo);
if(iter!=m_mapActions.end())
{
Action<T>* pAction = iter->second;
if(pAction) pAction->Execute(m_pInstance);
}
}
template<typename T>
bool State<T>::DoOnce( int iEvent )
{
ActionMap::iterator iter = m_mapActions.find(Action<T>::eOnEvent);
if(iter!=m_mapActions.end())
{
Action<T>* pAction = iter->second;
if(pAction)
{
if( pAction->GetEventId()==iEvent )
{
pAction->Execute(m_pInstance);
return true;
}
}
}
return false;
}
template<typename T>
int State<T>::Exit( int iEvent )
{
// Find the State to which this event is tied to
TransitionMap::iterator iter = m_mapTransitions.find(iEvent);
if(iter!=m_mapTransitions.end())
{
Transition* pTransition = iter->second;
ActionMap::iterator iterAc = m_mapActions.find(Action<T>::eOnExit);
if(iterAc!=m_mapActions.end())
{
Action<T>* pAction = iterAc->second;
if(pAction)
{
pAction->Execute(m_pInstance);
}
}
if(pTransition)
{
return pTransition->GetNextStateId();
}
}
return -1;
}
template<typename T>
void State<T>::AddTransition (int iEventId, int iStateId)
{
// Add a transition to the list
if (m_mapTransitions.size() < m_iMaxEventNum)
{
Transition* pTransition = new Transition;
pTransition->SetEventId( iEventId );
pTransition->SetNextStateId( iStateId );
m_mapTransitions.insert(TransitionMap::value_type(iEventId,pTransition));
}
}
template<typename T>
void State<T>::AddAction(int when, int type, int id, ActionFunc funcPtr)
{
if ( (when == Action<T>::eOnEntry)
|| (when == Action<T>::eDo)
|| (when == Action<T>::eOnExit) )
{
if ( type == Action<T>::eAction )
{
Action<T>* pAction = new Action<T>;
pAction->SetId(id);
pAction->SetType(type);
pAction->SetActionFunc(funcPtr);
m_mapActions.insert(ActionMap::value_type(when,pAction));
}
}
}
template<typename T>
void State<T>::AddAction(int when, int type, int id, int Eventid, ActionFunc funcPtr)
{
if ( (when == Action<T>::eOnEvent) )
{
if ( (type == Action<T>::eAction) && (m_mapActions.size() < m_iMaxEventNum) )
{
Action<T>* pAction = new Action<T>;
pAction->SetId(id);
pAction->SetType(type);
pAction->SetActionFunc(funcPtr);
pAction->SetEventId(Eventid);
m_mapActions.insert(ActionMap::value_type(when,pAction));
}
}
}
#pragma once
#include <list>
#include "State.h"
#include "../../Game/GameEvent.h"
template<typename T>
class StateMachine
{
typedef std::list<State<T>*> StateList;
public:
StateMachine(){}
virtual ~StateMachine()
{
DeleteSTLContainer( m_listStates );
}
public:
virtual bool InEvent (int iEvent = 0);
virtual bool OnEvent(int iEvent);
virtual bool OutEvent (int iEvent);
virtual void AddState( State<T> * pState );
virtual State<T>* CreateState(T* pT);
//
State<T>* GetCurState() const { return m_pCurState; }
void SetCurState(State<T>* pState) { m_pCurState = pState; }
State<T>* GetState(int iStateId);
private:
StateList m_listStates;
State<T>* m_pCurState;
};
template<typename T>
bool StateMachine<T>::InEvent (int iEvent)
{
if( GetCurState() != NULL )
{
return GetCurState()->Enter(iEvent);
}
return false;
}
template<typename T>
bool StateMachine<T>::OutEvent (int iEvent)
{
if( !m_listStates.empty() && GetCurState() )
{
State<T>* pNextState = GetState( GetCurState()->Exit(iEvent) );
if(pNextState!=NULL)
{
SetCurState(pNextState);
return GetCurState()->Enter(iEvent);
}
else
{
return OnEvent(iEvent);
}
}
return false;
}
template<typename T>
bool StateMachine<T>::OnEvent (int iEvent)
{
if( GetCurState() )
{
return GetCurState()->DoOnce(iEvent);
}
return false;
}
template<typename T>
State<T>* StateMachine<T>::CreateState(T* pT)
{
State<T>* pState = new State<T>(pT);
m_listStates.push_back(pState);
SetCurState( pState );
return pState;
}
template<typename T>
void StateMachine<T>::AddState( State<T> * pState )
{
m_listStates.push_back(pState);
SetCurState( pState );
}
template<typename T>
State<T>* StateMachine<T>::GetState(int iStateId)
{
State<T>* pState = NULL;
StateList::iterator iter = m_listStates.begin();
for(iter;iter!=m_listStates.end();++iter)
{
if((*iter)->GetId() == iStateId)
{
pState = (*iter);
break;
}
}
return pState;
}
~ 欢迎留言讨论 ~ 代码调试通过可使用,转载请注明出处,谢谢 ~