天天看點

【木頭Cocos2d-x 024】狀态機篇(第03章) --真正的狀态機來了~!

【Cocos2d-x 狀态機篇】第03章--真正的狀态機來了~!

笨木頭花心貢獻,啥?花心?不呢,是用心~

轉載請注明,原文位址:http://blog.csdn.net/musicvs/article/details/8348353

正文:

前面兩章介紹了一大堆東西,但似乎一直沒有看到狀态機這個東東,第02章裡面說的那些,看起來也就是普通的狀态模式的應用,我們似乎感覺不到狀态機的存在啊~(雖然那确實是狀态機的應用)。

(旁白:是的,是的~!我光顧着吐槽,都忘了這點了= =)

那麼,現在,我們來建立一個狀态機類,它不神秘,它僅僅是用來管理對象的狀态相關的東西,讓MutouT類得到解脫。

1. 建立MutouTFSM類

有限狀态機簡稱FSM,我們現在來建立這樣一個類:

/*
    檔案名:    MutouTFSM.h
    描 述:    木頭對象的狀态機,用來管理狀态
    建立人:    笨木頭 (CSDN部落格:http://blog.csdn.net/musicvs)

    建立日期:   2012.12.19
*/
#ifndef __MUTOUT_FSM_H__
#define __MUTOUT_FSM_H__

#include "cocos2d.h"
USING_NS_CC;

class I_State;
class MutouT;

class MutouTFSM : public CCNode {
public:
    static MutouTFSM* createWithMutouT(MutouT* mutou);
    bool initWithMutouT(MutouT* mutou);
    
    virtual void update(float dt);

    void changeState(I_State* state);   /* 切換狀态 */

private:
    /* 存放目前狀态類 */
    I_State* mCurState;

    /* 木頭對象 */
    MutouT* mMutou;
};

#endif
           

有沒有發現這個MutouTFSM和之前的MutouT類有點像?

現在,所有和狀态有關的操作都放到MutouTFSM狀态機類,MutouT類隻要專心地做他該做的事情就好了(休息、寫代碼、寫教程)。

看看MutouTFSM的實作:

#include "MutouTFSM.h"
#include "MutouT.h"
#include "I_State.h"

MutouTFSM* MutouTFSM::createWithMutouT( MutouT* mutou ) {
    MutouTFSM* fsm = new MutouTFSM();

    if(fsm && fsm->initWithMutouT(mutou)) {
        fsm->autorelease();
    }
    else {
        CC_SAFE_DELETE(fsm);
        fsm = NULL;
    }

    return fsm;
}

bool MutouTFSM::initWithMutouT( MutouT* mutou ) {
    this->mCurState = NULL;
    this->mMutou = mutou;
    mMutou->retain();
    return true;
}

void MutouTFSM::changeState( I_State* state ) {
    CC_SAFE_DELETE(mCurState);

    this->mCurState = state;
    
}

void MutouTFSM::update( float dt ) {
    this->mCurState->execute(mMutou);
}
           

很簡單,MutouTFSM會儲存一份MutouT對象,然後在update函數裡執行目前狀态的execute函數,簡單的說,就是,MutouT類的changeState和update函數都放到MutouTFSM裡了。

2. 被解放的MutouT類

我們再來看看新的MutouT類:

#ifndef __MUTOU_T_H__
#define __MUTOU_T_H__

#include "cocos2d.h"
#include "MutouTFSM.h"
USING_NS_CC;

class I_State;
//class MutouTFSM;

class MutouT : public CCNode {
public:
    CREATE_FUNC(MutouT);
    virtual bool init();

    bool isTire();                      /* 判斷是否寫代碼寫累了 */
    bool isWantToWriteArticle();        /* 是否想寫教程 */
    void writeCode();                   /* 寫代碼 */
    void writeArticle();                /* 寫教程 */
    void rest();                        /* 休息 */

    MutouTFSM* getFSM();                /* 擷取狀态機對象 */

    virtual void update(float dt);
private:
    /* 木頭狀态機 */
    MutouTFSM* mFSM;
};
#endif
           

(旁白:你這個騙紙~!這個MutouT不是還有update函數嗎?)

看到了吧,MutouT類多了一個MutouTFSM狀态機變量,changeState和update函數已經被去掉了~

(旁白:喂,你假裝看不到我嗎?那個update函數很明顯還在啊喂~!!)

然後我們看看MutouT的實作:

#include "MutouT.h"
#include "I_State.h"
#include "MutouTFSM.h"

bool MutouT::init() {
    mFSM = MutouTFSM::createWithMutouT(this);
    mFSM->retain();
    this->scheduleUpdate();
    return true;
}

bool MutouT::isTire() {
    /* 每次問木頭累不累,他都會說:累~ */
    return true;
}

bool MutouT::isWantToWriteArticle() {
    /* 有10%的機率想寫教程(好懶~!) */
    float ran = CCRANDOM_0_1();
    if(ran < 0.1f) {
        return true;
    }

    return false;
}

void MutouT::writeCode() {
    CCLOG("mutou is wirting Code.");
}

void MutouT::writeArticle() {
    CCLOG("mutou is writing article.");
}


void MutouT::rest() {
    CCLOG("mutou is resting.");
}

MutouTFSM* MutouT::getFSM() {
    return this->mFSM;
}

void MutouT::update( float dt ) {
    this->mFSM->update(dt);
}
           

和以前的實作是一樣的,隻是少了changeState函數,并且,留意到update函數了嗎?

void MutouT::update( float dt ) {

    this->mFSM->update(dt);

}

是的,它實際上是調用了狀态機的update函數。

(旁白:我就說它還在嘛。。。)

3. 這樣抽離一個MutouTFSM狀态機類有什麼好處?

為嘛這麼大費周章地整一個狀态機類倒底有什麼用?沒發現什麼新功能啊~

當然有用了,首先,這樣做每個類的職責分明,就好比老大讓我去做美工的工作,我才不願意~!我可是一個寫代碼的人~

(旁白:噗。沒事,我就吐吐槽。)

然後,萬一以後我們想給MutouT類換狀态呢?狀态類的接口改了呢?(雖然這很不應該)難道我們要打開我們的MutouT類去修改嗎?

(旁白:這有什麼問題?)

其實我也不知道這有什麼問題,是以我用了反問語氣,希望能騙過讀者~

(旁白:你可愛的妹紙的~!)

好了,到此為止,我們已經可以很好地使用狀态機了...

啊才怪啊~!還不夠~

我們不應該用update函數的~!

項目源碼下載下傳:  http://download.csdn.net/detail/musicvs/4912216

下一章,我們将介紹用事件驅動讓我們的狀态機完成無所不能的事情~!

繼續閱讀