cocos2dx 3.0 了解有限状态机02

来源:互联网 发布:mac上photoshop 编辑:程序博客网 时间:2024/05/16 23:02

上一篇胡乱的介绍了一下状态机,这就是面向过程的,哪里是出OO的,想cocos2dx 这样面向对象的引擎,还是找一种设计模式比较好,考虑到状态模式适用于这样的场景:

1.一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为。
2.一个操作中含有庞大的多分支结构,并且这些分支决定于对象的状态。

果断采用状态模式来试一下,据说有限状态机是依据这种模式来实现的,这里就先用状态模式来实现一下吧。
点此了解状态模式

1.我们要设计一个BaseState类,由该类抽象出writeCodeState,GoSleepState, GoToClassState 类。
2.然后修改AS类(在上篇有源码),将AS中的枚举去掉,谁让我们已经写了各种状态类了呢,就不要枚举了。将curState成员变量类型改为BaseState,多态就是这么屌。

现在是不是感觉有点像策略模式,其实还是比较好区别的,
点此了解一下区别

说这么多,还是来点实例靠谱,上代码

头文件#ifndef __STATE__H__#define __STATE__H__#include "AS.h"class AS;class BaseState {public:    virtual void excute(AS* as) = 0;};class WirteCodeState : public BaseState {    void excute(AS* as);};class GoToClassState : public BaseState {    void excute(AS* as);};class GoSleepState : public BaseState {    void excute(AS* as);};#endif
源文件#include "State.h"#include "cocos2d.h"void WirteCodeState::excute(AS* as) {    if (as->isTired()) {          as->GoSleep();      //睡觉去        as->changeState(new GoSleepState());    }}void GoToClassState::excute(AS* as) {    if (as->isTired()) {        as->GoSleep();        as->changeState(new GoSleepState());    }}void GoSleepState :: excute(AS* as) {    if (as->isWantToWriteCode()) {        as->WriteCode();        as->changeState(new WirteCodeState());    }    else {        as->GoToClass();  //上课        as->changeState(new GoToClassState());    }}

再来改变一下AS类

#ifndef __AS__H__#define __AS__H__#include "cocos2d.h"#include "State.h"USING_NS_CC;class BaseState;class AS :public Node {public:    virtual bool init(); //覆写    CREATE_FUNC(AS); //构造函数    //判断是否累了    bool isTired() { return true; };    //判断是否想写代码    bool isWantToWriteCode();    //休息睡觉    void GoSleep();    //写代码    void  WriteCode();    //上课    void GoToClass();    //切换状态    void changeState(BaseState* endState);    //gengxin    virtual void update(float dt);public:    BaseState* curState; //当前的状态};#endif
#include "AS.h"USING_NS_CC;bool AS::init() {    if (!Node::init()) {        return false;    }    this->scheduleUpdate();    return true;}bool AS::isWantToWriteCode() {    float tmp = CCRANDOM_0_1(); //睡不着的情况下就是不想写啊    if (tmp < 0.1f) {        return true;    }    return false;}void AS::GoSleep() {    CCLOG("AS will sleep!");}void AS::GoToClass() {    CCLOG("AS will go to class!");}void AS::WriteCode() {    CCLOG("AS will write code!");}/*    切换状态*/void AS::changeState(BaseState* endstate) {    this->curState = endstate;}/*    更新每帧*/void AS::update(float dt) {    curState->excute(this);}

置于执行类,几乎没有什么变化,chageState参数变了而已。

bool HelloWorld::init(){    //////////////////////////////    // 1. super init first    if ( !Layer::init() )    {        return false;    }    Size visibleSize = Director::getInstance()->getVisibleSize();    Vec2 origin = Director::getInstance()->getVisibleOrigin();    auto as = AS::create();    this->addChild(as);    //初始化为睡觉状态    as->changeState(new GoSleepState());    return true;}

运行结果
AS will sleep!
AS will go to class!
AS will sleep!
AS will go to class!
AS will sleep!
AS will go to class!
AS will sleep!
AS will go to class!
AS will sleep!
AS will write code!
AS will sleep!
AS will write code!

和之前最大的区别就是update了,是不是相对简单了,这样再添加写博客状态时候,就不用在改变AS了,直接再写一个子类就好了,这才是面向对象的效果嘛。
缺点也很明显,状态太多,需要创建太多的类。
看来还有更好的状态机,继续去学习

0 0
原创粉丝点击