笨木头  2012-12-20 12:56     Cocos2d-x,Cocos2d-x2.0     阅读(8121)     评论(9)
转载请注明,原文地址: http://www.benmutou.com/archives/40
文章来源:笨木头与游戏开发

Cocos2d-x 状态机篇】第01--花5分钟告诉你什么是有限状态机

 

笨木头花心贡献,啥?花心?不呢,是用心~

转载请注明,原文地址
 http://blog.csdn.net/musicvs/article/details/8348308

 

正文:

 

 

1. 简单认识

在游戏开发中,状态机几乎是必不可少的,关于状态机的专业解释,大家请百度一下。

简单地说,状态机就是控制游戏对象在不同的状态下应该做什么事情的一个机制(帅帅地提示一下,它很强大,强大到你无法想象~

(旁白:= =大家别信他,木头常常说谎)

 

2. 来写一个很好玩的游戏吧~

比如,我们要写一个很厉害很好玩的游戏,这个游戏的设想是这样的:

游戏世界里有一个木头,这个木头很多兴趣爱好。比如,他一有空就会写代码,写累了他就会停下来,然后...敲代码,敲累之后,他就会...写代码。可有时候他会突发奇想地要写一篇教程,因为他刚刚学会了新知识迫不及待的要分享。

就是这样,一个兴趣爱好广泛的木头,每天都干着这些多姿多彩的事情。

(旁白:很多兴趣爱好?我怎么看来看去就看到写代码? = =

 

3. 开始进入正题

那么,这个木头有这么多种状态,我们应该怎么用程序去实现这个逻辑呢?对了~!就是用状态机。

刚刚只是开了一个玩笑,写代码和敲代码是同一件事情,木头只有两种状态:写代码和写教程,以及休息。

(旁白:你可爱的妹纸的...不是说只有两种状态吗?)

 

4. 木头类代码

/*
    文件名:    Mutou.h
    描 述:    木头角色
    创建人:    笨木头 (CSDN博客:http://blog.csdn.net/musicvs)

    创建日期:   2012.12.16
*/
#ifndef __MUTOU_H__
#define __MUTOU_H__

#include "cocos2d.h"
USING_NS_CC;

enum EnumState{
    enStateWriteCode,       /* 状态:写代码 */
    enStateWriteArticle,    /* 状态:写教程 */
    enStateRest,            /* 状态:休息 */
};

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

    /* 当前状态 */
    EnumState enCurState;

    /* 判断是否写代码写累了 */
    bool isTire();

    /* 是否想写教程 */
    bool isWantToWriteArticle();

    /* 写代码 */
    void writeCode();

    /* 写教程 */
    void writeArticle();

    /* 休息 */
    void rest();

    /* 切换状态 */
    void changeState(EnumState enState);


    virtual void update(float dt);
};

#endif


 

#include "Mutou.h"

bool Mutou::init(){
    this->scheduleUpdate();
    return true;
}

void Mutou::changeState( EnumState enState ) {
    this->enCurState = enState;
}

bool Mutou::isTire() {
    /* 每次问木头累不累,他都会说:累~ */
    return true;
}

bool Mutou::isWantToWriteArticle() {
    /* 有10%的概率想写教程(好懒~!) */
    float ran = CCRANDOM_0_1();
    if(ran < 0.1f) {
        return true;
    }

    return false;
}

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

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


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

void Mutou::update( float dt ) {
    /* 判断在每一种状态下应该做什么事情 */
    switch(enCurState) {
    case enStateWriteCode:
        /* 如果累了就休息,并且切换到休息状态 */
        if(isTire()) {
            rest();
            changeState(enStateRest);
        }
        break;
    case enStateWriteArticle:
        /* 如果累了就休息,并且切换到休息状态 */
        if(isTire()) {
            rest();
            changeState(enStateRest);
        }
        break;
    case enStateRest:
        /* 一定的概率写代码,一定的概率写教程,并且切换到相应的状态 */
        if(isWantToWriteArticle()) {
            writeArticle();
            changeState(enStateWriteArticle);
        }
        else {
            writeCode();
            changeState(enStateWriteCode);
        }
        break;
    }
}


 

这是一个很简单的类,他有一些函数,用来做一些事情,他还有一个状态,表示他当前正在做什么事情。

接着,留意到Mutou类的update函数了吗? 我们在update函数里做一些事情(如果你不知道Cocos2d-xupdate函数的相关知识和使用方式,请百度一下,有很多资料~

其实,注释已经很详细了,判断木头当前的状态,在不同状态下又会做出一些行为,并且改变状态。

(旁白:我总感觉很简单的东西被你一写就不简单了= =

 

5. 开始让木头活起来~!

现在,我们来随便新建一个Cocos2d-x项目,然后把HelloWorldSceneinit函数多余的东西删掉,加入我们需要的代码:

bool HelloWorld::init()
{
    bool bRet = false;
    do 
    {
        CC_BREAK_IF(! CCLayer::init());

        /* 新建木头角色 */
        mMutou = Mutou::create();

        /* 初始化木头的状态为休息 */
        mMutou->changeState(enStateRest);

        this->addChild(mMutou);
        bRet = true;
    } while (0);

    return bRet;
}


 

很简单,我们给HelloWorld类加了一个成员变量mMutou,然后在init里新建了一个Mutou对象,并且把它的状态初始化为休息。

我们用调试模式运行程序,将看到以下日志的输出:

mutou is wirting Code.

mutou is resting.

mutou is wirting Code.

mutou is resting.

mutou is writing article.

mutou is resting.

mutou is wirting Code.

mutou is resting.

mutou is wirting Code.

这实在是太神奇了~!这就是状态机,如此简单,却又如此强大。

他可以完成很复杂的事情(包括人工智能~!)。

 

用我的理解,那就是一句话:对象在面对不同情况时,根据自身的状态做出不同的响应,并且对象的状态个数是有限的。

 

好了,强大的状态机(其实我介绍的确切的说应该叫做“有限状态机”)就是这么简单。关于状态机的教程到此结束,大家可以开始去实现那复杂无比的AI逻辑了,比如战斗系统中怪物的AI行为。

(旁白:等等~!总觉得哪里不对劲!你的标题不是写着第一章么?怎么就到此结束了?第二章呢?还有啊,这算什么代码啊?一大串逻辑塞在switch语句里!!)

 

我就说旁白怎么这么久都没有出来吐槽呢~

开玩笑的,目前这个例子确实是介绍有限状态机应用的好例子,但是它不实用,真正有用的实现方式还多着呢~

下一章我们将简单介绍地介绍一下状态模式。

 

9 条评论
  • griffin445615105 2012-12-20 13:59:00

    写得太好啦~~
    0回复
  • musicvs 2012-12-20 14:07:00

    [reply]griffin445615105[/reply]
    谢谢支持~
    0回复
  • musicvs 2012-12-20 14:08:00

    [reply]griffin445615105[/reply]
    谢谢支持~
    0回复
  • raaland 2012-12-24 00:30:00

    有意思的状态机
    0回复
  • musicvs 2012-12-24 08:04:00

    [reply]raaland[/reply]
    嘿嘿,谢谢~
    0回复
  • start530 2013-01-15 10:02:00

    每次看木头的博客都有意料之外的收获,也不知道是你的教程太好,还是我的领悟能力强,想象力丰富!(旁白:噗,你这是夸博主还是夸你自己)

    这次有两个收获,一个是知道状态机到底干嘛的,另一个就是对C++的应用有了更深的了解诶。
    0回复
  • musicvs 2013-01-15 14:06:00

    [reply]start530[/reply]
    噗,谢谢~那当然是在夸我了~嘿嘿
    0回复
  • qq634416025 2013-03-03 02:07:00

    嘿嘿 简单的尝试翻译了一片国外的博客文章讲的也是状态机。。。。不过没你这个专业 哈哈http://blog.csdn.net/qq634416025/article/details/8630226
    0回复
  • musicvs 2013-03-03 08:01:00

    [reply]qq634416025[/reply]
    你客气了,哈哈
    0回复
发表评论
粤ICP备16043700号

本博客基于 BlazorAnt Design Blazor 开发