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

1 状态模式

State是状态基类。它其实是一个接口,它有3个实现类,分别对应每个状态。Monkey类只需要维护State类,而具体的行为通过3个实现类完成。这就是多态。下面是完整的代码:

2 状态基类

// State.h
//
#ifndef STATE_H_
#define STATE_H_

class Monkey;

struct State
{
   virtual void execute(Monkey *mk) = 0;
};

#endif // STATE_H_

3 实现类

3.1 StopState

// StopState.h
//
#ifndef STOP_STATE_H_
#define STOP_STATE_H_

#include "State.h"
#include "Monkey.h"

class StopState
    : public State
{
public:
    virtual void execute(Monkey *mk);
};

#endif // STOP_STATE_H_

// StopState.cpp
//
#include "StopState.h"
#include "WalkState.h"

void StopState::execute(Monkey *mk)
{
    if (mk->isStopTimeout()) {
        mk->changeState(new WalkState());
        mk->walk();
    }
}

3.2 WalkState

// WalkState.h
//
#ifndef WALK_STATE_H_
#define WALK_STATE_H_

#include "State.h"
#include "Monkey.h"

class WalkState
    : public State
{
public:
    virtual void execute(Monkey *mk);
};

#endif // WALK_STATE_H_

// WalkState.cpp
//
#include "WalkState.h"
#include "TurnState.h"
#include "StopState.h"

void WalkState::execute(Monkey *mk)
{
    mk->walk();

    if (mk->isWalkOutBorder()) {
        mk->changeState(new TurnState());
        mk->turn();
    } else if (mk->isWalkTimeout()) {
        mk->changeState(new StopState());
        mk->stop();
    }
}

3.3 TurnState

// TurnState.h
//
#ifndef TURN_STATE_H_
#define TURN_STATE_H_

#include "State.h"
#include "Monkey.h"

class TurnState
    : public State
{
public:
    virtual void execute(Monkey *mk);
};

#endif // TURN_STATE_H_

// TurnState.cpp
//
#include "TurnState.h"
#include "WalkState.h"

void TurnState::execute(Monkey *mk)
{
    mk->changeState((State*) new WalkState());
    mk->walk();
}

4 Monkey

#ifndef MONKEY_H_
#define MONKEY_H_

#include <time.h>

#include "cocos2d.h"
USING_NS_CC;

#include "State.h"

#define MAX_STOP_TIME  10
#define MAX_WALK_TIME  20

#define MAX_WALK_DIST  100

class Monkey
    : public Node
{
public:
    Monkey()
    {
        log("Monkey()");
    }

    CREATE_FUNC(Monkey);

    virtual bool init()
    {
        _curPos = 0;
        _step = 1;

        _curState = 0;

        this->scheduleUpdate();

        return true;
    }

    void changeState(State * newState)
    {
        State * oldState = _curState;
        _curState = newState;

        if (oldState) {
            delete oldState;
        }
        _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)
    {
        if (_curState) {
            _curState->execute(this);
        }
    }

private:
    State * _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_

5 总结

当我们需要添加了一种新的状态时,不需要去修改长长的条件判断语句了,只需要构造一个新的状态类,修改它的前序和后序状态类就可以了。对于任何一个状态的特有行为,都是独立的,不会混杂在其它状态的代码里。原为决定状态转移逻辑的那个长长的条件语句不见了,而是被分布在State的子类之间。另一方面,从设计的角度看,原先对当前状态的标识,是FSM内部的一个自有变量,状态与状态之间的转换也仅仅是表现为对自有变量的赋值,如果这个自有变量衍生为变量数组时,那极易出现FSM内部状态不一致的情况,而State的引入可以使得这样的情况变得相当简单。对于新版本的FSM来说,状态与状态之间的转换也成了原子化的操作,不需要兼顾多个变量的赋值。

既然所有状态机具有同样的规则和范式,那么状态机应该与具体对象无关,完全可以提炼出纯粹的状态机类来管理任何对象的状态。下节就完成这个任务。

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) (一) 参考:http://blog.csdn.net/mgphuang/article/details/5845252<Cocos2d-x游 ...

  4. 《C++游戏开发》笔记十二 战争迷雾:初步实现

    本系列文章由七十一雾央编写,转载请注明出处.  http://blog.csdn.net/u011371356/article/details/9475979 作者:七十一雾央 新浪微博:http:/ ...

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

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

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

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

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

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

  8. 整理了一下浅墨大神的Visual C++/DirectX 9.0c的游戏开发手记

    还是非常棒的博客,只是没有一个文件夹.所以自己做了一个山寨文件夹在这里.便于随时查找. 前面31期从略. [Visual C++]游戏开发笔记三十二 浅墨DirectX提高班之中的一个 DirectX ...

  9. HTML5物理游戏开发 - 越野山地自行车(三)粉碎自行车

    自上一章公布到如今已时隔四月,实在对不住大家.让大家久等了~话说不是我不关注我的博客,而是事情一多起来写博客的时间就少了. 待到今日有空了,回头看了看自己曾经写的文章,猛得发现已经四个月不曾写文章了. ...

随机推荐

  1. Swift:Minimizing Annotation with Type Inference

    许多程序猿更喜欢比如Python和Javascript这样的动态语言,因为这些语言并不要求程序猿为每个变量声明和管理它们的类型. 在大多数动态类型的语言里,变量可以是任何类型,而类型声明是可选的或者根 ...

  2. 微信小程序基础之input输入框控件

    今天主要详写一下微信小程序中的Input输入框控件,输入框在程序中是最常见的,登录,注册,获取搜索框中的内容等等都需要,同时,还需要设置不同样式的输入框,今天的代码中都要相应的使用. input输入框 ...

  3. The Zen Programmer

    专注 何为专注 关于 休息 怎么睡觉 心无杂念 我的体会 自我分析 初学者心态 无我 不要设置职业目标 敏事慎言 正念 做自己的老板 玩物养志 结语 最近在研读Christian Grobmeier ...

  4. Spring之AOP模块

    AOP(Aspect Oriented Programming,面向切面编程)是Spring框架的一个重要特征 Spring推荐使用接口编程 Spring提供三种拦截器:方法前拦截器.返回后拦截器.异 ...

  5. Android的SharedPreferences(首选项)保存键值对

    使用共享首选项 如果您有想要保存的相对较小键值集合,您应使用 SharedPreferences API.SharedPreferences 对象指向包含键值对的文件并提供读写这些文件的简单方法. 每 ...

  6. 有N个数,组成的字符串,如012345,求出字串和取MOD3==0的子串,如012 12 123 45。

    #include <iostream> using namespace std; int getSum(string str, int begin, int len) { int sum ...

  7. GridView如何适配不同屏幕

    GridView和ListView一样,都是项目中常用的控件之一,那么本篇文章要讲的是GridView如何适应不同大小的屏幕,首先,我们来看一张效果图,如下: 每行为四个item,上下左右间距大概2d ...

  8. FFmpeg源代码简单分析:常见结构体的初始化和销毁(AVFormatContext,AVFrame等)

    ===================================================== FFmpeg的库函数源代码分析文章列表: [架构图] FFmpeg源代码结构图 - 解码 F ...

  9. 对N各集合中的任意元素进行排列组合问题

    小李去市场买菜,有蔬菜(茄子.黄瓜.大白菜...等k中素菜),和肉类(牛肉,羊肉,鸡肉...等m种荤菜),及点心(麻饼,桃酥,枣花...等n中点心),现在老婆要求每天一荤一素一点心 并且每天的样式要尽 ...

  10. Android的ToggleButton和Switch以及AnalogColok和DigitalColok的用法-android学习之旅(二十)

    ToggleButton 和Switch简介 ToggleButton 和Switch都是继承了Button,所以他们的属性设置和Button差不多. 分别支持的属性 ToggleButton 的属性 ...