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. [django] 利用多线程增加异步任务

    看到django异步大家的反应应该是celery这种消息队列组件,现在用的最多的最推荐的也是这种方式.然而我这需求就是请求来了,执行一个小程序,但是又不能确定这个小程序啥时候执行完,响应又要及时,丢给 ...

  2. nginx反向代理和rewrite进行解决跨域问题、去掉url中的一部分字符串,通过nginx正则生成新的url

    场景:表面上访问的是http://127.0.0.1:7777/test/xhtml//tpl/app-tpl-webapp/css/base.css, 实际上看的是http://127.0.0.1: ...

  3. JQuery 网页选项卡制作

    网页选项卡可以较好的利用有限的页面来展示更多的元素,而使用JQuery来制作网页选项卡也是一件非常简单的事情.今天就来分享一个网页选项卡的制作小技巧. 引入所需库 选项卡原理 业务核心 完整小例子 引 ...

  4. Android WebView选择本地文件上传

    This sample demonstrate android webview choose file to upload. I just implement the client code ,the ...

  5. 剑指offer-面试题7:俩个栈实现队列(c)

  6. iOS开发关于适配iOS10以及Xcode8的相关新知识

    一.证书管理 用Xcode8打开工程后,比较明显的就是下图了,这个是苹果的新特性,可以帮助我们自动管理证书.建议大家勾选这个Automatically manage signing(Ps.但是在bea ...

  7. ROS_Kinetic_24 使用catkin_create_qt_pkg快速创建qt-ros功能包

    使用catkin_create_qt_pkg快速创建qt-ros功能包 参考网址: qt_create:http://wiki.ros.org/qt_create qt_ros:https://git ...

  8. 初探linux子系统集之timer子系统(一)

    一般来说要让整个linux系统跑起来,那么一个必须的就是linux的时钟,也就是时间子系统了,这里正好工作需要,那么就研究下linux下的时间子系统了. linux内核必须完成两种主要的定时测量.一个 ...

  9. JQuery纵向下拉菜单实现心得

    jquery库给我们带来了许多便利,不愧是轻量级的DOM框架,在前面的博文中小编分别对jquery的基础知识以及jquery的一些小demo有一系列的简单介绍,期待各位小伙伴的指导.使用jquery实 ...

  10. 安卓banner图片轮播

    之前写过一篇关于首页图片广告轮播的demo:http://blog.csdn.net/baiyuliang2013/article/details/45740091,不过图片轮播的指示器(小白点)处操 ...