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都幫咱們生成好了。

相關文章
相關標籤/搜索