一、简介
利用有限状态机来控制对象的行为,其原理就是利用多态,常常我们自己写代码,需要很大篇幅,万一需要再加一个或者几个状态,那么我们自己维护时就会很麻烦,SMC这个工具可以帮助我们解决这个问题。
使用这个工具之前我们需要jdk环境,最新版的SMC支持jdk1.7,之前版本的SMC支持jdk1.6,要想中间没有问题,我们一定要将电脑上的jdk版本与SMC的jdk版本对应起来。
SMC1.6下载地址:http://download.csdn.net/detail/wu_123_456/7635941
SMC1.7下载地址:http://download.csdn.net/detail/wu_123_456/7635975
SMC可以通过一个配置文件,生成有限状态机所需的所有状态类以及状态机类,同时还包括了所有的状态间的转换逻辑。
SMC支持多种开发语言:C、JavaScript、Python、C++、Lua、Ruby、C#、Objective-C、Scala、Groovy、Perl、TCL、Java、PHP、VB.net,而我们所需要做的唯一的工作就是编写拥有这些状态的主体类。
二、编写smc文件
首先写一个sm的文件:
// 指定初始状态
%start HelloMap::SayingHello
// 实体对象
%class Hello
// 实体对象头文件
%header Hello.h
// 存放状态对象的类
%map HelloMap
%%
// State Transition End State Action(s)
SayingHello
Entry {
sayHello();
}
Exit {
}
{
// 这里可以填写该状态转换到其他状态的逻辑
}
%%
(1.)%start HelloMap::SayingHello:%start标签用于定义对象的初始状态,SayingHello是一个状态类,稍后解释。
(2.)%class Hello:%class标签用于定义状态的主体对象,也就是说,指定哪个类具备这些状态和行为。
(3.)%header Hello.h:%header标签用于定义主体对象的头文件。
(4.)%map HelloMap:重点来了,%map标签用于定义状态表对象的名称。什么是状态表呢?SMC在生成状态机代码时,会将对象的各种状态都创建为静态对象。
而状态表存放所有的静态变量。
(5.)%%...%%:这一对%%中间定义了各个状态类以及状态的各种行为。Entry{}代表在切换到该状态时要执行的事件,Ext{}表示离开改状态时要执行的事件,Entry和Exit是有限
状态机常用的技巧,可以在开始和结束时执行一些动作。后面有一对花括号用于定义状态的行为,比如状态在执行到哪个函数后切换到另外一个状态,以及切换状态时要
执行的动作。也就是状态存活期间的行为。
三、如何执行,参考下面图集
如何查看本地jdk版本,打开doc界面,输入java -version,即可。
四、问题,如果jdk版本不匹配,一定要下载与之对应的,这个问题折腾了一上午
6.3.0版本显示结果:Could not find the main class
&unsupported ....version 51的问题,由于本地的jdk版本java -version
下查询得出是1.6,但是smc6.3.0版本支持的是jdk1.7,所以要么更改本地的
jdk版本,要么更改smc版本成6.1.0(jdk1.6)
五、手动添加代码部分,Hello.h和Hello.cpp文件
#ifndef __HELLO_H__
#define __HELLO_H__
#include "HelloSMC_sm.h"
#include "cocos2d.h"
USING_NS_CC;
class Hello:public CCNode
{
public:
virtual bool init();
void sayHello();
CREATE_FUNC(Hello);
private:
HelloSMCContext* smcContent;//状态机
CCLabelTTF* m_label;
};
#endif//__HELLO_H__
#include "Hello.h"
bool Hello::init()
{
bool bRet = false;
do
{
CCSprite* sprite = CCSprite::create("run1.png");
this->addChild(sprite);
m_label = CCLabelTTF::create("haunghua","Arial",35);
m_label->setPosition(ccp(120,0));
this->addChild(m_label);
smcContent = new HelloSMCContext(*this);
smcContent->setDebugFlag(true);
smcContent->enterStartState();
bRet = true;
} while (0);
return bRet;
}
void Hello::sayHello()
{
CCLOG("sayHello");
m_label->setString("Hello SMC");
}
最后要写改HelloWorldScene中init函数:
Hello* mhello = Hello::create();
mhello->setPosition(ccp(100,200));
this->addChild(mhello);