php fsm 状态机,浅谈状态机FSM设计方法

看了一晚上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<:string basefsm> mStatusCollection;

public:

//命令一些实体去达到某个状态

void Transaction(std::vector & 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 & 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<:string basefsm>::iterator it = 0;

if((it = mStatusCollection.find(stateName)) != mStatusCollection.end())

{

mStatusCollection.erase(it);

}

}

//获取状态机

BaseFsm * FsmManager::FindFsm(const char * stateName)

{

std::map<: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<:string basefsm>::iterator it = mStatusCollection.begin(); it!= mStatusCollection.end(); it++)

{

BaseFsm * fsm = it->second;

if(fsm)

delete fsm;

}

}

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值