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次的判断。

在上面的状态机中,其实是让这个对象在不同的状态中表现出了不同的行为特征,那不同的行为特征之间除了有类似的形式化的接口之外,基本上没有任何的联系。那我们很自然地想到状态模式,利用状态模式维护状态,实现对象与维护状态的分离。

cocos2d-x 游戏开发之有限状态机(FSM) (一)的更多相关文章

  1. cocos2d-x 游戏开发之有限状态机(FSM) (四)

    cocos2d-x 游戏开发之有限状态机(FSM) (四) 虽然我们了解了FSM,并且可以写自己的FSM,但是有更好的工具帮我们完成这个繁琐的工作.SMC(http://smc.sourceforge ...

  2. cocos2d-x 游戏开发之有限状态机(FSM) (三)

    cocos2d-x 游戏开发之有限状态机(FSM) (三) 有限状态机简称FSM,现在我们创建一个专门的FSM类,负责管理对象(Monkey)的状态.然后Monkey类就实现了行为与状态分离.Monk ...

  3. cocos2d-x 游戏开发之有限状态机(FSM) (二)

    cocos2d-x 游戏开发之有限状态机(FSM)  (二) 1 状态模式

  4. iOS cocos2d 2游戏开发实战(第3版)书评

    2013是游戏爆发的一年,手游用户也是飞速暴增.虽然自己不做游戏,但也是时刻了解手机应用开发的新动向.看到CSDN的"写书评得技术图书赢下载分"活动,就申请了一本<iOS c ...

  5. java游戏开发杂谈 - 有限状态机

    在不同的阶段,游戏所运行的逻辑.所显示的界面,都是不同的. 以五子棋举例,游戏开始.游戏中.胜负已分,对应的界面和逻辑都不同. 在游戏中,又分为:自己下棋.对方下棋.游戏暂停.悔棋等多个状态. 再比如 ...

  6. (转载)如何学好iphone游戏开发

    转自:http://www.cnblogs.com/zilongshanren/archive/2011/09/19/2181558.html 自从发布<如何学习iphone游戏开发>到 ...

  7. 游戏开发设计模式之状态模式 & 有限状态机 & c#委托事件(unity3d 示例实现)

    命令模式:游戏开发设计模式之命令模式(unity3d 示例实现) 对象池模式:游戏开发设计模式之对象池模式(unity3d 示例实现) 原型模式:游戏开发设计模式之原型模式 & unity3d ...

  8. cocos2d 游戏开发实战

    文章转自:http://uliweb.clkg.org/tutorial/read/40 6   cocos2d 游戏开发实战 6.1   创建cocos2d项目 6.2   cocos2d v3 & ...

  9. 【Cocos2D研究院之游戏开发】

    http://www.xuanyusong.com/archives/category/ios/cocos2d_game 分类目录归档:[Cocos2D研究院之游戏开发]   201211-19 Co ...

随机推荐

  1. Android对话框Dialog深度剖析

    对话框 对话框是提示用户作出决定或输入额外信息的小窗口. 对话框不会填充屏幕,通常用于需要用户采取行动才能继续执行的模式事件. 对话框设计 Dialog 类是对话框的基类,但您应该避免直接实例化 Di ...

  2. TV Metro界面(仿泰捷视频TV版)源码解析

    转载请把头部出处链接和尾部二维码一起转载,本文出自逆流的鱼yuiop:http://blog.csdn.net/hejjunlin/article/details/52822499 前言:上一篇介绍了 ...

  3. 等价于n*n的矩阵,填写0,1,要求每行每列的都有偶数个1 (没有1也是偶数个),问有多少种方法。

    #define N 4 /* * 公式: * f(n) = 2^((n - 1) ^2) */ int calWays(int n) { int mutiNum = (n - 1) * (n - 1) ...

  4. Java异常处理-----自行处理

    自行处理 1.try{//可能发生异常的代码 }catch(异常类 变量名){//处理}. 2.案例除法运算的异常处理. 3.如果没有进行try catch处理,出现异常程序就停止.进行处理后,程序会 ...

  5. Java线程状态

    线程跟人类一样拥有自己的生命周期,一条线程从创建到执行完毕的过程即是线程的生命周期,此过程可能在不同时刻处于不同的状态,线程状态正是这小节的主题,线程到底有多少种状态?不同状态之间是如何转化的? 对于 ...

  6. UE4实现闪烁效果

    官网文档链接:http://docs.unrealengine.com/latest/CHN/Engine/Rendering/Materials/ExpressionReference/Math/i ...

  7. Microsoft Dynamics CRM2011 更换Logo

    之前操作过但没做过记录,这里记录下以防以后有需要时记不起来还有迹可循 IE收藏栏的图标,在网站根目录下的的/favicon.ico CRM网页中的Logo,替换/_imgs/crmmastheadlo ...

  8. TDD实践感悟

    每个开发者都想开发出高质量的代码,更少的Bug.更容易维护不仅让人心情愉悦,也让我们有更多时间去学习和生活. 少加一些班,多陪家人,:) 当开发任务非常简单时,比如基本的增删改查,可能使用怎样的方式开 ...

  9. J2EE进阶(十一)SSH框架整合常见问题汇总(二)

    org.hibernate.PropertyAccessException: IllegalArgumentException occurred while calling setter of cn. ...

  10. tomcat如何路由映射网址

    对于web容器来说,根据请求客户端路径路由到对应的资源属于其核心功能,假设用户在自己电脑上使用浏览器输入网址http://www.test.com/test/index.jsp,报文通过互联网网络到达 ...