SMC --- COCOS2D-X 状态机代码生成工具

1、简介      java

        利用有限状态机来控制对象的行为,其原理就是利用多态,经常咱们本身写代码,须要很大篇幅,万一须要再加一个或者几个状态,那么咱们本身维护时就会很麻烦,SMC这个工具能够帮助咱们解决这个问题。c++

      使用这个工具以前咱们须要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,而咱们所须要作的惟一的工做就是编写拥有这些状态的主体类。this

2、编写smc文件spa

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

 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 %%

其中:code

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

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

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

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

  五、%%...%%:这一对%%中间定义了各个状态类以及状态的各类行为。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的路径

3、添加实体类

  业务逻辑仍然要咱们本身实现,那就是写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 }

4、状态机类

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

5、使用

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

6、总结

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

相关文章
相关标签/搜索