Cocos2d-x Game Development Limited state Machine (FSM) (iv)
Although we know the FSM and can write our own FSM, there are better tools to help us with this tedious task. SMC (http://smc.sourceforge.net/) is such a tool. :
Http://sourceforge.net/projects/smc/files/latest/download
The Smc.jar below the bin is the command-line tool used to build the status class. Use the following command:
$ Java-jar Smc.jar Monkey.sm
1 Real-world FSM
First define a state machine plain text file: Monkey.sm, which reads as follows:
cheungmine//2015-01-22//entity Class%class monkey//entity class Header%header monkey.h//inital state%start MonkeyMa p::stop//entity State Map%map Monkeymap%%stopentry {STOP ();} Exit {exit ();} {Walk Walk {}} Walkentry {walk ();} Exit {exit ();} {Stop Stop {}turn turn {}} Turnentry {turn ();} Exit {exit ();} {Walk Walk {}}%%
Where%class Monkey describes the name of the entity class: Monkey (Monkey.h and Monkey.cpp)
%header specified header file: Monkey.h
%map indicates the state diagram class, which contains all states. Here is: Monkeymap
%start indicates the status, here is STOP, the corresponding class is: Monkeymap_stop
The sections between%%...%% define each state. The format is as follows:
Stop //state name Entry { //execute this function to enter the state Stop ();} Exit { //execute this function to exit the state exit ();} { //state Toggle Logic walk Walk {}}
When you run the following command, the files are automatically generated: Monkey_sm.h and Monkey_sm.cpp. Join the project together with your own statemap.h.
Java-jar Smc.jar Monkey.sm
2 entity classes
The business logic still needs our own realization, that is writes Monkey.h and Monkey.cpp. But this time write monkey class need to follow certain rules, the following is the source code:
monkey.h//#ifndef monkey_h_#define monkey_h_#include "Cocos2d.h" USING_NS_CC; #include "monkey_sm.h" #define Max_ Stop_time 3#define max_walk_time 10#define max_walk_dist 200class monkey:public node{public:create_func (Monkey); virtual BOOL init (); void Stop (); void Walk (); void Turn (); void exit ();p Rivate:monkeycontext * _FSM; int _step; int _curpos; time_t _curtime; Sprite * _sprite;private:void onidlestop (float dt) {int d = (int) (Time (0)-_curtime); if (d > Max_stop_time) {_fsm->walk (); }} void Onidlewalk (float dt) {if (_curpos > Max_walk_dist | | _curpos <-max_walk_dist) { _fsm->turn (); } int d = (int) (Time (0)-_curtime); if (d > Max_walk_time) {_fsm->stop (); } _curpos + = _step; } void Onidleturn (float dt) {_fsm->walk (); }}; #endif//Monkey_h_
Above the OnIdle???? Is the callback function that triggers the state, and the business logic for entity state change is implemented here.
monkey.cpp//#include "Monkey.h" #include <time.h> #include <assert.h>void monkey::exit () {this-> Unscheduleallcallbacks (); Cocos2d::log ("Exit ()");} BOOL Monkey::init () {_step = 1; _curpos = 0; _curtime = time (0); _sprite = Sprite::create ("Monkey.png"); AddChild (_sprite); _FSM = new Monkeycontext (*this); ASSERT (_FSM); _fsm->setdebugflag (TRUE); _fsm->enterstartstate (); return true;} void Monkey::stop () {_curtime = time (0); Cocos2d::log ("Stop (): pos=%d", _curpos); This->schedule (Schedule_selector (monkey::onidlestop), 0.1f);} void Monkey::walk () {_curtime = time (0); Cocos2d::log ("Walk (): pos=%d", _curpos); This->schedule (Schedule_selector (Monkey::onidlewalk), 0.1f);} void Monkey::turn () {_step *=-1; Cocos2d::log ("Turn (): step=%d", _step); This->schedule (Schedule_selector (Monkey::onidleturn), 0.1f); }
3 state Machine Class
The framework code SMC has helped us build: Monkey_sm.h and Monkey_sm.cpp:
Ex:set ro://do not edit.//generated by SMC (http://smc.sourceforge.net/)//from file:monkey.sm//#ifndef monkey_s M_h#define monkey_sm_h#define smc_uses_iostreams#include "statemap.h"//Forward Declarations.class Monkeymap;class Monkeymap_stop;class monkeymap_walk;class monkeymap_turn;class Monkeymap_default;class MonkeyState;class Monkeycontext;class monkey;class monkeystate:public statemap::state{public:monkeystate (const char * const name, C onst int Stateid): statemap::state (name, Stateid) {}; virtual void Entry (monkeycontext&) {}; virtual void Exit (monkeycontext&) {}; virtual void Stop (monkeycontext& context); virtual void Turn (monkeycontext& context); virtual void Walk (monkeycontext& context);p rotected:virtual void Default (monkeycontext& context);}; Class Monkeymap{public:static Monkeymap_stop STOP; Static Monkeymap_walk WALK; Static Monkeymap_turn TURN;}; Class Monkeymap_default:public Monkeystate{publIc:monkeymap_default (const char * const name, const int Stateid): monkeystate (name, Stateid) {};}; Class Monkeymap_stop:public Monkeymap_default{public:monkeymap_stop (const char * const name, const int Stateid) : Monkeymap_default (name, Stateid) {}; virtual void Entry (monkeycontext&); virtual void Exit (monkeycontext&); virtual void Walk (monkeycontext& context);}; Class Monkeymap_walk:public Monkeymap_default{public:monkeymap_walk (const char * const name, const int Stateid) : Monkeymap_default (name, Stateid) {}; virtual void Entry (monkeycontext&); virtual void Exit (monkeycontext&); virtual void Stop (monkeycontext& context); virtual void Turn (monkeycontext& context);}; Class Monkeymap_turn:public Monkeymap_default{public:monkeymap_turn (const char * const name, const int Stateid) : Monkeymap_default (name, Stateid) {}; virtual void Entry (monkeycontext&); virtual void Exit (MONKEYContext&); virtual void Walk (monkeycontext& context);}; Class Monkeycontext:public Statemap::fsmcontext{public:explicit Monkeycontext (monkey& owner): FSMContext ( Monkeymap::stop), _owner (&owner) {}; Monkeycontext (monkey& owner, Const statemap::state& State): Fsmcontext (state), _owner (&owner) {}; virtual void Enterstartstate () {getState (). Entry (*this); } inline monkey& GetOwner () {return *_owner; }; Inline monkeystate& getState () {if (_state = = NULL) {throw statemap::stateundefinedexcep tion (); } return dynamic_cast<monkeystate&> (*_state); }; inline void Stop () {getState (). Stop (*this); }; inline void Turn () {getState (). Turn (*this); }; inline void Walk () {getState (). Walk (*this); };p rivate:monkey* _owner;}; #endif//monkey_sm_h////Local variables://buffer-read-only:t// end://
Ex:set ro://do not edit.//generated by SMC (http://smc.sourceforge.net/)//from file:monkey.sm//#include "Monkey . h "#include" monkey_sm.h "using namespace statemap;//Static class declarations. Monkeymap_stop monkeymap::stop ("Monkeymap::stop", 0); Monkeymap_walk Monkeymap::walk ("Monkeymap::walk", 1); Monkeymap_turn Monkeymap::turn ("Monkeymap::turn", 2); void Monkeystate::stop (monkeycontext& context) {Default ( context);} void Monkeystate::turn (monkeycontext& context) {Default (context);} void Monkeystate::walk (monkeycontext& context) {Default (context);} void Monkeystate::D efault (monkeycontext& context) {throw (transitionundefinedexception (context). GetState (). GetName (), context.gettransition ());} void Monkeymap_stop::entry (monkeycontext& context) {monkey& ctxt = Context.getowner (); Ctxt.stop ();} void Monkeymap_stop::exit (monkeycontext& context) {monkey& ctxt = Context.getowner (); Ctxt.exit ();} void MonkeymAp_stop::walk (monkeycontext& context) {context.getstate (). Exit (context); Context.setstate (Monkeymap::walk); Context.getstate (). Entry (context);} void Monkeymap_walk::entry (monkeycontext& context) {monkey& ctxt = Context.getowner (); Ctxt.walk ();} void Monkeymap_walk::exit (monkeycontext& context) {monkey& ctxt = Context.getowner (); Ctxt.exit ();} void Monkeymap_walk::stop (monkeycontext& context) {context.getstate (). Exit (context); Context.setstate (Monkeymap::stop); Context.getstate (). Entry (context);} void Monkeymap_walk::turn (monkeycontext& context) {context.getstate (). Exit (context); Context.setstate (Monkeymap::turn); Context.getstate (). Entry (context);} void Monkeymap_turn::entry (monkeycontext& context) {monkey& ctxt = Context.getowner (); Ctxt.turn ();} void Monkeymap_turn::exit (monkeycontext& context) {monkey& ctxt = Context.getowner (); Ctxt.exit ();} void Monkeymap_turn::walk (monkeycontext& context) { Context.getstate (). Exit (context); Context.setstate (Monkeymap::walk); Context.getstate (). Entry (context);} Local variables://buffer-read-only:t//end://
4 Summary
FSM is a fixed paradigm, so using tools to help us achieve the opportunity to reduce mistakes. The input file is: entity. Sm. We focus on the business logic, so the state-related code of SMC helps us build it. Compare the classes that we created manually and automatically generated by the SMC Framework tool:
The use of Cocos2d-x is simple:
BOOL Helloworld::init () { ////////////////////////////// //1. Super init first if (! Layer::init ()) { return false; } Auto RootNode = Csloader::createnode ("MAINSCENE.CSB"); AddChild (RootNode); Auto Closeitem = static_cast<ui::button*> (Rootnode->getchildbyname ("button_1")); Closeitem->addtoucheventlistener (Cc_callback_1 (Helloworld::menuclosecallback, this)); Test/////////////////////// Monkey * mk = monkey::create (); AddChild (MK); return true;}
That's it! Do not understand the place please read carefully:
Cocos2d-x Game Development Tour (Jong Dirong)
Cocos2d-x Game Development Limited state Machine (FSM) (iv)