在游戏中使用面向对象的FSM
以前一直是用switch的状态机,因为J2ME没办法用太多类,现在改做c++了,终于可以试一试面向对象的状态机了,代码果然简洁了好多。参考的是《Programming Game AI by Example》第2章,大约改了下。首先要定义一个状态基类:
这是一个模板类,因为状态要对应不同的所有者,比如游戏状态的所有者是游戏类Game,而主角状态这里的entity_type就是主角类Hero。总之,状态对于状态拥有者实体是依赖关系。因为实体有很多种状态,所以要定义具体的状态子类,比如主菜单状态是游戏状态类的子类:
状态子类采用了单件模式,所以状态子类中不能存放对于拥有者实体来说是自有的数据,比如有很多士兵,那么士兵的状态子类中就不能存放生命值,只能存放在实体中,在状态类中通过实体的指针去访问。我觉得状态采用单件更清晰些,数据就在实体中维护吧,当然也许每个实体有一个对应的状态实例也有合适的使用之处。
然后需要定义状态机类:
状态机类也是模板类,道理一样,每种实体必须有一个对应的状态机类,状态机和实体是聚合关系,状态机保存了实体的指针,从而让状态可以访问实体。状态机和状态既有聚合关系也有依赖关系,状态机维护了当前状态,上一个状态,以及一个全局状态,从而对当前及全局状态进行Update和Render,并且通过 ChangeState管理状态的切换,切换状态时要调用旧状态的OnExit和新状态的OnEnter,设置第一个状态比较特殊,所以我加了 SetFirstState,只有对新状态的处理,原书中是直接设置,这样不会调用OnEnter了。
最后看实体怎么使用状态机,比如有一个Game类,首先他需要拥有一个状态机实例(也是聚合关系):
class Game
{
StateMachine<Game>* m_pFSM;
};
这个实例可以在Game构造时构造好:
Game::Game(void)
{
m_pFSM = new StateMachine<Game>(this);
}
析构时删除
Game::~Game()
{
delete m_pFSM;
}
游戏初始化时可设置第一个状态:
m_pFSM->SetFirstState(GSLogo::GetInstance());//这里是显示Logo
在Game Update和Render时分别调用状态机的Update和Render即可
void Game::Update(float dt)
{
...
m_pFSM->Update(dt);
...
}
void Game::Render(float dt)
{
...
m_pFSM->Render(dt);
...
}
那么状态的切换呢?是在状态子类中进行的,比如游戏从主菜单进入关卡,在主菜单状态的Update逻辑中:
void GSMainMenu::Update(Game* pGame, float dt)
{
...
if(Start按钮按下)
{
pGame->GetFSM()->ChangeState(GSLevelLoading::GetInstance());
}
...
}
游戏类有GetFSM方法让状态类得到状态机,切换状态时直接调用相应状态类的GetInstance得到唯一的状态实例
总结:
1)实体拥有一个状态机,实体通过状态机的Update和Render来实现不同状态下的逻辑和渲染
2)状态机指向他的拥有者实体,并且聚合了状态,状态机通过Update和Render来让当前状态执行逻辑和渲染,并且状态机提供了统一的状态切换流程,即先Exit前一状态,然后设置当前状态,并Enter新状态
3)每个实体对应一个状态基类(通过模板化),以及若干子类(通过继承模板基类),状态子类是实体状态的具体实现者,状态子类进行实际的Update和 Render,并且通过实体指针访问实体数据和方法,状态切换也是通过状态子类进行的,即各个子类是独立的,这样能很方便的增加和删除状态,只要修改前后状态的切换就可以了。
分享到:
相关推荐
用于演示游戏AI中的FSM(有限状态机的实现),使用DirectX 7.0编写,如果无法使用请在博客留言
演示程序1为"用过程编程的方法实现FSM的源程序代码";演示程序2为"用面向对象方法实现FSM的源程序代码
fsm_hello
视频中工程代码 class8_FSM视频中工程代码 class8_FSM视频中工程代码 class8_FSM视频中工程代码 class8_FSM视频中工程代码 class8_FSM视频中工程代码 class8_FSM视频中工程代码 class8_FSM视频中工程代码 class8_FSM...
FSM-60S光纤熔接中文操作手册.pdf
有限状态机FSM在PLD中的实现分析.pdf
SNOW3G算法定义的有限状态机FSM,用于产生LFSR所需要的初始化输入F
一个FSM的基本骨架,可以根据自己的需要来...可以在几个角色间互相通讯,另外,虽然是在cocos2dx上编程的,但是基本没有关联,因此如果需要在cocos2dx上使用,还需要做些关联,如此,希望我的这份代码能够帮助到大家
otg_fsm.c - ChipIdea USB IP core OTG FSM driver.
FSM状态机的详细实现Demo请放心下载学习,多谢各位欣赏下载,多谢各位。
基于FSM的测试用例生成,FSM支持黑盒测试,如何生成测试用例一直是嵌入式软件测试的重要环节,论文首先讲述FSM,在此基础上提出正则表达式生成测试用例,并着重提出分解算法。
FSM软件系统中MATLAB并行计算的应用.pdf
计算机导论课本中的FSM自动机描述,实现不同状态转换
FSM状态机verilog实现,有限状态机的实现方式
verilog FSM 范例 //FSM always @(posedge clk or negedge rst_n)begin if(rst_n == 1'd0)begin sta_curr ; end else begin sta_curr ; end end always @(*)begin case(sta_curr) S_IDLE:begin if(s_idle_...
FSM初学者教程 FSM编程-菜鸟入门(清晰版)
Unity C# 《有限状态机》的用法教程详解Demo 助力快速理解 FSM 有限状态机,完成游戏状态的切换 教程地址:https://blog.csdn.net/ChinarCSDN/article/details/82263126
三段fsm设计,fpga三段状态机设计,fpga三段状态机设计,fpga三段状态机设计fpga三段状态机设计,fpga三段状态机设计fpga三段状态机设计
模型.fsm
使用JAVA语言编写的FSM状态机生成工具,可以产生C C++ JAVA版本的FSM状态机源程序,状态设计只需填写文本文件即可,非常实用,可以大大缩短状态机编程时间,并保证正确性。