Cocos2d-x game development-Finite State Machine (FSM) (4), cocos2d-xfsm

Source: Internet
Author: User
Tags fsm

Cocos2d-x game development-Finite State Machine (FSM) (4), cocos2d-xfsm
Cocos2d-x game development-Finite State Machine (FSM) (4)

Although we understand FSM and can write our own FSM, there are better tools to help us complete this tedious task. SMC (http://smc.sourceforge.net/) is such a tool. :

Http://sourceforge.net/projects/smc/files/latest/download

Smc. jar under bin is a command line tool used to generate status classes. Run the following command:

$ java -jar Smc.jar Monkey.sm

1. FSM in the real world

First, define a state machine plain text file: Monkey. sm. The content is as follows:

// cheungmine// 2015-01-22// entity class%class Monkey// entity class header%header Monkey.h// inital state%start MonkeyMap::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 {}}%%

Here, % class Monkey indicates the object class name: Monkey (Monkey. h and Monkey. cpp)

% Header specifies the header file: Monkey. h

% Map indicates the status chart class, which contains all States. Here is: MonkeyMap

% Start indicates the actual status. Here is STOP, and the corresponding class is MonkeyMap_STOP.

The section between %... % defines each status. The format is as follows:

STOP // status name Entry {// execute this function to enter this status stop ();} Exit {// execute this function to exit this status Exit exit ();} {// status switching logic walk {}}

When you run the following command, the system automatically generates the files Monkey_sm.h and Monkey_sm.cpp. Add the built-in statemap. h to the project.
java -jar Smc.jar Monkey.sm

2. entity class

We still need to implement the business logic by ourselves, that is, write Monkey. h and Monkey. cpp. However, this write of the Monkey class requires certain rules. The source code is as follows:

// 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();private:    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_

OnIdle ???? It is the callback function that triggers the state. The business logic of the 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

The frame code Smc has been generated for us: 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_SM_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, const 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);protected:    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::StateUndefinedException();        }        return dynamic_cast<MonkeyState&>(*_state);    };    inline void stop()    {        getState().stop(*this);    };    inline void turn()    {        getState().turn(*this);    };    inline void walk()    {        getState().walk(*this);    };private:    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::Default(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 reduce the chances of making mistakes. The input file is entity. sm. We focus on the business logic, so status-related code smc has been generated for us. Compare the manually created classes and automatically generated classes by the smc Framework tool:


Using in 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! Read the following carefully:

Cocos2d-x game development tour (Zhong Dilong)






Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.