zoukankan      html  css  js  c++  java
  • SMC --- COCOS2D-X 状态机代码生成工具

    一、简介      

            利用有限状态机来控制对象的行为,其原理就是利用多态,常常我们自己写代码,需要很大篇幅,万一需要再加一个或者几个状态,那么我们自己维护时就会很麻烦,SMC这个工具可以帮助我们解决这个问题。

          使用这个工具之前我们需要jdk环境,最新版的SMC支持jdk1.7,之前版本的SMC支持jdk1.6,要想中间没有问题,我们一定要将电脑上的jdk版本与SMC的jdk版本对应起来。

          下载地址:http://sourceforge.net/projects/smc/files/

          SMC可以通过一个配置文件,生成有限状态机所需的所有状态类以及状态机类,同时还包括了所有的状态间的转换逻辑。

          SMC支持多种开发语言:C、JavaScript、Python、C++、Lua、Ruby、C#、Objective-C、Scala、Groovy、Perl、TCL、Java、PHP、VB.net,而我们所需要做的唯一的工作就是编写拥有这些状态的主体类。

    二、编写smc文件

           首先写一个sm的文件     Hero.sm:

     1 // entity class  
     2 %class Hero  
     3    
     4 // entity class header  
     5 %header Hero.h  
     6    
     7 // inital state  
     8 %start HeroMap::STOP  
     9    
    10 // entity state map  
    11 %map HeroMap  
    12 %%  
    13 STOP  
    14 Entry {  
    15     stop();  
    16 }  
    17 Exit {  
    18     exit();  
    19 }  
    20 {  
    21     walk WALK {}  
    22 }  
    23    
    24 WALK  
    25 Entry {  
    26     walk();  
    27 }  
    28 Exit {  
    29     exit();  
    30 }  
    31 {  
    32     stop STOP {}  
    33     turn TURN {}  
    34 }  
    35    
    36 TURN  
    37 Entry {  
    38     turn();  
    39 }  
    40 Exit {  
    41     exit();  
    42 }  
    43 {  
    44     walk WALK {}  
    45 }  
    46 %%

    其中:

      1、%class Hero: %class标签用于定义状态的主体对象,也就是说,指定哪个类具备这些状态和行为。比如:Hero(Hero.h和Hero.cpp)

      2、%header Hero.h:%header标签用于定义主体对象的头文件。

      3、%start HeroMap::STOP:%start标签用于定义对象的初始状态,STOP是一个状态类,对应的类是:HeroMap_STOP。

      4、%map HeroMap:重点来了,%map标签用于定义状态表对象的名称。什么是状态表呢?SMC在生成状态机代码时,会将对象的各种状态都创建为静态对象。而状态表存放所有的静态变量(包含全部状态)。对应的是:HeroMap。

      5、%%...%%:这一对%%中间定义了各个状态类以及状态的各种行为。Entry{}代表在切换到该状态时要执行的事件,Ext{}表示离开改状态时要执行的事件,Entry和Exit是有限状态机常用的技巧,可以在开始和结束时执行一些动作。后面有一对花括号用于定义状态的行为,比如状态在执行到哪个函数后切换到另外一个状态,以及切换状态时要执行的动作。也就是状态存活期间的行为。格式如下:

     1 STOP    // 状态名  
     2    
     3 Entry {  
     4     // 执行这个函数进入该状态  
     5     stop();  
     6 }  
     7    
     8 Exit {  
     9     // 执行这个函数退出该状态  
    10     exit();  
    11 }  
    12    
    13 {  
    14     // 状态切换逻辑  
    15     walk WALK {}  
    16 }

      当运行下面的命令,会自动生成文件:Hero_sm.h和Hero_sm.cpp。连同自带的statemap.h一起加入到项目中。

    1 java -jar [$PATH]Smc.jar -c++ Hero.sm  //[PATH] smc.jar的路径

    三、添加实体类

      业务逻辑仍然要我们自己实现,那就是写Hero.h和Hero.cpp。不过这次写Hero类需要按一定的规则,下面是源代码:

     1 // Hero.h  
     2 //  
     3 #ifndef HERO_H_  
     4 #define HERO_H_  
     5    
     6 #include "cocos2d.h"  
     7 USING_NS_CC;  
     8    
     9 #include "Hero_sm.h"  
    10    
    11    
    12 #define MAX_STOP_TIME  3  
    13 #define MAX_WALK_TIME  10  
    14 #define MAX_WALK_DIST  200  
    15    
    16    
    17 class Hero : public Node  
    18 {  
    19     public:  
    20         CREATE_FUNC(Hero);  
    21        
    22         virtual bool init();  
    23        
    24         void stop();  
    25        
    26         void walk();  
    27        
    28         void turn();  
    29        
    30         void exit();  
    31        
    32     private:  
    33         HeroContext * _fsm;  
    34        
    35         int    _step;  
    36         int    _curPos;  
    37         time_t _curTime;  
    38        
    39         // Sprite * _sprite;  
    40        
    41     private:  
    42         void onStop(float dt)  
    43         {  
    44             int d = (int) (time(0) - _curTime);  
    45             if (d > MAX_STOP_TIME) {  
    46                 _fsm->walk();  
    47             }  
    48         }  
    49        
    50        
    51         void onWalk(float dt)  
    52         {  
    53             if (_curPos > MAX_WALK_DIST || _curPos < -MAX_WALK_DIST) {  
    54                 _fsm->turn();  
    55             }  
    56        
    57             int d = (int) (time(0) - _curTime);  
    58             if (d > MAX_WALK_TIME) {  
    59                 _fsm->stop();  
    60             }  
    61        
    62             _curPos += _step;  
    63         }  
    64        
    65        
    66         void onTurn(float dt)  
    67         {  
    68             _fsm->walk();  
    69         }  
    70 };  
    71    
    72 #endif // HERO_H_

    上面的on***是触发状态的回调函数,实体状态改变的业务逻辑在这里实现。

     1 // Hero.cpp  
     2 //  
     3 #include "Hero.h"  
     4    
     5 #include <time.h>  
     6 #include <assert.h>  
     7    
     8    
     9 void Hero::exit()  
    10 {  
    11     this->unscheduleAllCallbacks();  
    12     CCLOG("exit()");  
    13 }  
    14    
    15    
    16 bool Hero::init()  
    17 {  
    18     _step = 1;  
    19     _curPos = 0;  
    20     _curTime = time(0);  
    21    
    22     _fsm = new HeroContext(*this);  
    23     assert(_fsm);  
    24    
    25     _fsm->setDebugFlag(true);  
    26     _fsm->enterStartState();  
    27    
    28     return true;  
    29 }  
    30    
    31    
    32 void Hero::stop()  
    33 {  
    34     _curTime = time(0);  
    35    
    36     CCLOG("stop(): pos=%d", _curPos);  
    37    
    38     this->schedule(schedule_selector(Hero::onStop), 0.1f);  
    39 }  
    40    
    41    
    42 void Hero::walk()  
    43 {  
    44     _curTime = time(0);  
    45    
    46     CCLOG("walk(): pos=%d", _curPos);  
    47    
    48     this->schedule(schedule_selector(Hero::onWalk), 0.1f);  
    49 }  
    50    
    51    
    52 void Hero::turn()  
    53 {  
    54     _step *= -1;  
    55     CCLOG("turn(): step=%d", _step);  
    56    
    57     this->schedule(schedule_selector(Hero::onTurn), 0.1f);        
    58 }

    四、状态机类

      框架代码Smc已经帮我们生成好了:Hero_sm.h和Hero_sm.cpp。

    五、使用

    1 Hero* hero= Hero::create();  
    2 addChild(hero);

    六、总结

      FSM是一种固定的范式,因此采用工具帮我们实现可以减少犯错误的机会。输入的文件就是:实体.sm。我们把重点放在业务逻辑上,所以与状态有关的代码smc都帮我们生成好了。

  • 相关阅读:
    [rabbitmq] python版本(六)远程过程调用
    [rabbitmq] python版本(五) 主题交换机
    物体运动学习笔记(一)
    基于TimeLine编辑角色动画(二)
    基于TimeLine编辑角色动画(一)
    SQlite常用操作封装
    unity三种资源加载方式Resources,AssetBundle,WebRequset的同步异步加载
    场景同步异步加载
    XML保存账号密码
    unity EditorWindow 绘制时间刻度
  • 原文地址:https://www.cnblogs.com/atong/p/4555785.html
Copyright © 2011-2022 走看看