看了一晚上FSM方面的资料,颇有收获,写写感悟:
状态机,在游戏里面是非常重要的,最简单的状态机,莫过于
switch()
case 1:
if(not 反复执行状态1)
进入1状态前要做的准备
进入1状态的过程
if(not 反复执行状态1)
离开状态1的过程
case2:
...
但这种方式不能很有效预定义所有的状态,也不能把这些状态之间的切换过程合理的定义出来,“状态”本身没有一个合理的定义,几乎是一种面向过程的方式,只过这种方式足够简单,也最容易让人接受,缺点就没有“状态”的定义和指派功能,导致状态的混乱,出现状态处理重复代码,甚至处理不一致的问题,按照OO的观念,状态描述本来就应该是一种实体
比如“吃饭”这种状态,进入要做什么,进行时要做什么,退出时要做什么,需要进行一个描述,以下是我写的状态机管理策略:
//状态的定义
class State
{
public:
State();
State(const char * name);
//状态的名字
std::string statename;
//比较两个状态是否相同
inline bool operator ==(const State& other);
};
//状态机基类
class BaseFsm
{
public:
//状态机的状态描述
State state;
//进入状态
virtual void Enter(FsmEntity *entity);
//执行状态
virtual void Execute(FsmEntity *entity);
//离开状态
virtual void Exit(FsmEntity *entity);
//比较两个状态机是否相同
inline bool operator ==(const BaseFsm& other);
};
//状态机实体
class FsmEntity
{
protected:
//当前所使用的状态机
BaseFsm *mCurrentFsm;
public:
//构造函数
FsmEntity();
//析构函数
virtual ~FsmEntity();
//设置开始状态
void InitState(BaseFsm *fsm);
//状态是否初始化了
bool IsStateInited();
//保持状态的方法
void KeepState();
//返回当前的状态机
BaseFsm * GetCurrentFsm();
//改变状态
void ChangeState(BaseFsm *newFsm);
};
//状态机容器
class FsmManager
{
private:
//状态机容器的名称
std::string name;
//所有的状态集合
std::map<std::string, BaseFsm *> mStatusCollection;
public:
//命令一些实体去达到某个状态
void Transaction(std::vector<FsmEntity *> & entities, const char * stateName);
//令某个实体达到某个状态
void Transaction(FsmEntity * entity, const char * stateName);
//添加状态机
void AddFsm( BaseFsm * fsm);
//删除状态机
void RemoveFsm(const char * stateName);
//获取状态机
BaseFsm * FindFsm(const char * stateName);
//构造
FsmManager(const char *fsname);
//析构
virtual ~FsmManager();
};
State::State()
{
}
State::State(const char * name)
{
statename = name;
}
//构造函数
FsmEntity::FsmEntity()
{
mCurrentFsm = 0;
}
//析构函数
FsmEntity::~FsmEntity()
{
}
//返回当前的状态机
BaseFsm * FsmEntity::GetCurrentFsm()
{
return mCurrentFsm;
}
//状态是否初始化了
bool FsmEntity::IsStateInited()
{
if(mCurrentFsm)
return true;
else
return false;
}
//设置当前状态
void FsmEntity::InitState(BaseFsm *fsm)
{
if(mCurrentFsm == 0)
{
mCurrentFsm = fsm;
}
else
{
LOG(0, WARN_LV, "初始状态已经设定");
}
}
//保持状态的方法
void FsmEntity::KeepState()
{
mCurrentFsm->Execute(this);
}
//改变状态
void FsmEntity::ChangeState(BaseFsm *newFsm)
{
if(mCurrentFsm)
//离开原来的状态
mCurrentFsm->Exit(this);
//设定现有状态
mCurrentFsm = newFsm;
//进入现有状态
mCurrentFsm->Enter(this);
//执行现有的状态
mCurrentFsm->Execute(this);
}
//比较两个状态是否相同
bool State::operator ==(const State& other)
{
return statename == other.statename;
}
//进入状态
void BaseFsm::Enter(FsmEntity *entity)
{
LOG(0, DEBUG_LV, "进入%s状态", state.statename.c_str());
}
//执行状态
void BaseFsm::Execute(FsmEntity *entity)
{
LOG(0, DEBUG_LV, "执行%s状态", state.statename.c_str());
}
//离开状态
void BaseFsm::Exit(FsmEntity *entity)
{
LOG(0, DEBUG_LV, "离开%s状态", state.statename.c_str());
}
bool BaseFsm::operator ==(const BaseFsm& other)
{
return state == other.state;
}
//命令一些实体去达到某个状态
void FsmManager::Transaction(std::vector<FsmEntity *> & entities, const char * stateName)
{
for(size_t i = 0; i < entities.size(); i ++)
{
FsmEntity *entity = entities[i];
Transaction(entity, stateName);
}
}
//令某个实体达到某个状态
void FsmManager::Transaction(FsmEntity * entity, const char * stateName)
{
if(entity->GetCurrentFsm() && entity->GetCurrentFsm()->state.statename == stateName)
{
entity->KeepState(); //保持之前的状态
}
else
{
BaseFsm * fsm = mStatusCollection[stateName];
if(fsm)
{
//执行状态
entity->ChangeState(fsm);
}
else
{
LOG(0, ERROR_LV, "找不到%s状态", stateName);
}
}
}
//添加状态机
void FsmManager::AddFsm( BaseFsm * fsm)
{
if(mStatusCollection.find(fsm->state.statename.c_str()) != mStatusCollection.end())
return; //已经添加过了
//添加
mStatusCollection[fsm->state.statename] = fsm;
}
//删除状态机
void FsmManager::RemoveFsm(const char * stateName)
{
std::map<std::string, BaseFsm *>::iterator it = 0;
if((it = mStatusCollection.find(stateName)) != mStatusCollection.end())
{
mStatusCollection.erase(it);
}
}
//获取状态机
BaseFsm * FsmManager::FindFsm(const char * stateName)
{
std::map<std::string, BaseFsm *>::iterator it = 0;
if((it = mStatusCollection.find(stateName)) != mStatusCollection.end())
{
BaseFsm * fsm = it->second;
return fsm;
}
return 0;
}
//构造
FsmManager::FsmManager(const char *fsname)
{
name = fsname;
LOG(0, DEBUG_LV, "构造状态机容器 %s", fsname);
}
//析构
FsmManager::~FsmManager()
{
//移出所有的状态机
for(std::map<std::string, BaseFsm *>::iterator it = mStatusCollection.begin(); it!= mStatusCollection.end(); it++)
{
BaseFsm * fsm = it->second;
if(fsm)
delete fsm;
}
}