cocos2d-x 游戏开发之有限状态机(FSM) (一)
cocos2d-x 游戏开发之有限状态机(FSM) (一)
参考:
http://blog.csdn.net/mgphuang/article/details/5845252
《Cocos2d-x游戏开发之旅》(钟迪龙)
基本上所有的软件都是有限状态机(finite-state machine,FSM)。它是一个有向图,由一组节点和一组相应的转移函数组成。通俗点讲,它是一个事件驱动系统的模型,这个模型由有限数目的状态,若干输入和状态与状态之间转换的规则组成。在某一时刻,有一个或一组状态是FSM的当前状态,FSM接收输入事件并根据转换规则,将当前状态转为新的状态。正是由于这三个元素的组合,使得FSM具备了自己的行为特点。在游戏开发中,FSM被用来实现人工智能的决策过程,控制游戏对象的行为。
1 最简单的状态机
可能上面的解释还是有些抽象,绝大多数的文章会举用“门”或“锁”的例子来说明什么是状态机,我想还是举一个新鲜的例子吧:有一个叫做“猴子”的NPC,它会在指定的区域里行走,有时候停留,当行走到区域的边界所时,会自己转向(图1)。我们把状态机的转换规则函数列出表格(图2),并根据列出的规则写出是这个简单状态机的C++实现:
#ifndef MONKEY_H_ #define MONKEY_H_ #include <time.h> #include "cocos2d.h" USING_NS_CC; #define MAX_STOP_TIME 10 #define MAX_WALK_TIME 20 #define MAX_WALK_DIST 100 enum MonkeyState { stSTOP, stWALK, stTURN }; class Monkey : public Node { public: Monkey() { log("Monkey()"); } CREATE_FUNC(Monkey); virtual bool init() { _curPos = 0; _step = 1; changeState(stSTOP); this->scheduleUpdate(); return true; } void changeState(MonkeyState newState) { _curState = newState; _curTime = time(0); } void stop() { cocos2d::log("stop()"); } void walk() { _curPos += _step; cocos2d::log("walk(): pos=%d", _curPos); } void turn() { _step *= -1; cocos2d::log("turn(): step=%d", _step); } void update(float dt) { switch (_curState) { case stSTOP: if (isStopTimeout()) { changeState(stWALK); walk(); } break; case stWALK: walk(); if (isWalkOutBorder()) { changeState(stTURN); turn(); } else if (isWalkTimeout()) { changeState(stSTOP); stop(); } break; case stTURN: changeState(stWALK); walk(); break; } } private: MonkeyState _curState; time_t _curTime; int _curPos; int _step; public: bool isStopTimeout() { return (time(0) - _curTime > MAX_STOP_TIME); } bool isWalkTimeout() { return (time(0) - _curTime > MAX_WALK_TIME); } bool isWalkOutBorder() { return (_curPos > MAX_WALK_DIST || _curPos < -MAX_WALK_DIST); } }; #endif // MONKEY_H_
2 坏代码的味道
显然,如果继续将上面的代码写完整的话,它一定能很好的工作。但我似乎已经闻到了传说中“坏代码”的味道,上面长长的条件判断语句,会随着状态的增多变得更长。每增加一个状态,就需要在长长的条件判断语句中小心查找和修改。当这样的条件语句增长到需要多个人合作完成时,那当导致严重的维护与调试方面的问题。另外,对于编译型语言而言,一个具有N个状态的FSM要查找一个正确的状态,平均需要进行N/2次的判断。
在上面的状态机中,其实是让这个对象在不同的状态中表现出了不同的行为特征,那不同的行为特征之间除了有类似的形式化的接口之外,基本上没有任何的联系。那我们很自然地想到状态模式,利用状态模式维护状态,实现对象与维护状态的分离。
最新文章
- MYSQL批量修改表前缀与表名sql语句
- Window Ghosting
- 使用SQL Server Audit记录数据库变更
- EasyUI datagrid 行编辑
- R语言学习笔记(一)
- web storm
- 详细解读MySQL中的权限
- 适应所有浏览器的cookie
- UVALive 6525 Attacking rooks 二分匹配 经典题
- 查看实时公网ip
- ORACLE查看和更改的最大连接数
- Google photos -- reverse thinking
- [知了堂学习笔记]_用JS制作《飞机大作战》游戏_第2讲(四大界面之间的跳转与玩家飞机的移动)
- 《JAVA程序设计》_第九周学习总结
- MT【249】离心率两题
- logstash报错401 需要在logstash启动的配置文件中增加es的用户名和密码
- 30.SSH配置文件模板和类库.md
- poj 1523Tarjan算法的含义——求取割点可以分出的连通分量的个数
- 负载均衡(Load Balancing)学习笔记(一)
- 关于Eclipse如何加入Gradle文件与Android Studio两个平台一起开发,工作目录不发生变化
热门文章
- 【SSH系列】Hibernate映射 -- 继承映射
- PGM:部分观测数据
- Racket 模拟SICP的流(延时计算)
- Maven简介(Maven是什么)
- Spring之AOP模块
- JAVA面向对象-----extends关键字
- JAVA面向对象-----封装
- C语言中switch case语句可变参实现方法(case 参数 空格...空格 参数 :)
- 18 UI美化自定义主题样式代码
- [ExtJS5学习笔记]第十八节 Extjs5的panel的dockeditems属性配置toolbar