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

来源:互联网 发布:ubuntu 一直等待安装 编辑:程序博客网 时间:2024/06/11 05:49

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  100class 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来说,状态与状态之间的转换也成了原子化的操作,不需要兼顾多个变量的赋值。

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



1 0
原创粉丝点击