qfFSM有限状态自动机类库目前拥有C++、C#、Java、JavaScript版本,对于同一份UML状态图,不同语言均可用qfFSM来实现。

本文使用JavaScript版本在浏览器中实现一个超时按钮,为方便测试,我使用鼠标指针来模拟Kinect关节,接入Kinect数据后,只需将手部关节坐标替换进来即可。

首先看超时按钮的UML状态图:

主状态机中有STATE_Normal、STATE_PointIn、STATE_PointOut三个状态,其中后面两个作为子状态机存在,他们内部分别含有3个状态:激活/非激活开始状态、正在激活/非激活状态、已激活/非激活状态。

设计 正在激活/非激活状态 是为了配合相应动画机制,如经典的按钮注水、按钮转满一周等计时方式。

事件方面支持UserLeave、PointIn、PointOut,以及MultiActive(多次连续激活)。

MultiActive机制可以很方便的实现 保持按住按钮,系统会周期触发某个事件。

源码中分为以下几个部分:

1、首先定义了各种常量:状态名称、事件名称、属性名称:

var timeoutButton_const_def = { … };

2、定义数据模型Model实现类:

var TimeoutButton_Model = { … };

在Model中定义各种属性,如激活时间、指针是否在对象可视范围内、计时器开始和结束。

3、定义各个子状态机、状态的实现类,他们分别继承自qfStateMachine/qfState基类,并实现doAction()事件:

var State_Normal = { … };

var STATE_PointIn = { … };

var STATE_PointOut = { … };

var STATE_Active_start = { … };

var STATE_Activing = { … };

var STATE_Actived = { … };

var STATE_DeActive_start = {… };

var STATE_DeActiving = { … };

var STATE_DeActived = { … };

4、定义了主逻辑状态机,继承自qfFsmLogic基类:

var timeoutButton_Logic = { … };

其中核心方法为状态机初始化函数(initTimeoutButtonMachine()成员函数),包含三个方面:

1)设置状态机环境变量,此处只设置数据模型Model,以便各个状态获取数据属性。

2)实例化各个子状态机、状态,并绑定到各自父状态机中。

3)配置状态转移规则,这里完成对UML状态图的描述翻译。

5、实例化主逻辑状态机,并调用他的start()方法:

var timeoutButton = timeoutButton_Logic.createNewInstance();

timeoutButton.start();

6、绑定mouseover、mouseout事件,完成OnTimer()函数,将来的Kinect数据获取也是一个周期性事件,直接放在此处即可。

7、最后是界面的Html代码,其中包含一个多次激活标志checkbox、还有一个支持超时激活的按钮(DIV实现),如下图:

其中Current State为状态机当前状态,可以实时看到状态转移过程。

实现DEMO展示Url:qfFSM_for_javascript_kinect_timeoutButton

源代码右键查看即可。

qfFSM各版本源码下载:http://www.YuYuYouEr.cn/blog/?p=290