FenoFSM Usage
General Workflow
The general workflow for FenoFSM involves the following steps:
- Create a finite state machine.
- Create states for the finite state machine.
- Create transitions for the finite state machine.
- Register event listeners to states and transitions.
- Feed the finite state machine inputs to trigger state transitions.
Each state and transition:
- Has its own unique name in a finite state machine.
- Is created through the FSMachine.createState() or FSMachine.createTransition() builder method.
If a state's or transitions's name is not specified, the finite state machine will automatically generate a unique name for it.
You can obtain a state's or transition's reference from a finite state machine through the FSMachine.getStateByName() or FSMachine.getTransitionByName() method.
Creating A Finiter State Machine
The FSMachine class represents the finite state machine.
The first thing to do is to instantiate an FSMachine object.
import idv.cjcat.fenofsm.*;
//The parameter passed to the constructor is the initial state's name.
var fsm:FSMachine = new FSMachine("s0");Creating States
States are created through the FSMachine.createState() method.
The initial state's reference can be obtained by accessing the FSMachine.initState property.
var s0:State = fsm.initState;
//the parameter passed to the method is the newly created state's name.
var s1:State = fsm.createState("s1");
var s2:State = fsm.createState("s2");Creating Transitions
Transitions are created through the FSMachine.createTransition() method.
Transition creation requires the following parameters:
- The origin state of transition.
- The destination state of transition.
- A unique transition name.
- The input that triggers the transition.
- Transition delay time (optional).
Note that the transition's input must be a primitive object.
//a transition from state 's0' to state 's1', with input "forward", name "t01", and delay time 0
var t01:Transition = fsm.createTransition(s0, s1, "forward", "t01", 0);
//a transition from state 's1' to state 's2', with input "forward", name "t12", and delay time 0
var t12:Transition = fsm.createTransition(s1, s2, "forward", "t12", 0);
//a transition from state 's2' to state 's0', with input "forward", name "t20", and delay time 0
var t20:Transition = fsm.createTransition(s2, s0, "forward", "t20", 0);
//a transition from state 's0' to state 's2', with input "backward", name "t02", and delay time 0
var t02:Transition = fsm.createTransition(s0, s2, "backward", "t02", 0);
//a transition from state 's2' to state 's1', with input "backward", name "t21", and delay time 0
var t21:Transition = fsm.createTransition(s2, s1, "backward", "t21", 0);
//a transition from state 's1' to state 's0', with input "backward", name "t10", and delay time 0
var t10:Transition = fsm.createTransition(s1, s0, "backward", "t10", 0);
Registering Event Listeners
A StateEvent.ENTER event is dispatched by a state when a finite state macine enters that state.
A StateEVent.EXIT event is dispatched by a state when a finite state machine leaves that state.
A TransitionEvent.INIT event is dispatched right after its origin state dispatches the StateEvent.EXIT event.
A TransitionEvent.COMPLETE event is dispatched right before its destination state dispatches the StateEvent.ENTER event.
If a transition's delay time is set to a positive number (in seconds), the transition dispatches a TransitionEvent.INIT event, waits for a while (the wait time is the delay time), dispatches a TransitoinEvent.COMPLETE event, and finally enters the destination state.
During the delay, the transition repeatedly dispatches TransitionEvent.PROGRESS events; these events have a progress property which spcifies the current progress percentage of delay.
If the delay time is set to a negative value, the transition will delay infinitely until the Transition.go() method is called. During the infinite delay, the finite state machine remains in the origin state and is said to be "frozen".
import idv.cjcat.fenofsm.events.*;
s0.addEventListener(StateEvent.ENTER, stateListener);
s0.addEventListener(StateEvent.EXIT, stateListener);
s1.addEventListener(StateEvent.ENTER, stateListener);
s1.addEventListener(StateEvent.EXIT, stateListener);
s2.addEventListener(StateEvent.ENTER, stateListener);
s2.addEventListener(StateEvent.EXIT, stateListener);
t01.addEventListener(TransitionEvent.INIT, transitionListener);
t01.addEventListener(TransitionEvent.COMPLETE, transitionListener);
t12.addEventListener(TransitionEvent.INIT, transitionListener);
t12.addEventListener(TransitionEvent.COMPLETE, transitionListener);
t20.addEventListener(TransitionEvent.INIT, transitionListener);
t20.addEventListener(TransitionEvent.COMPLETE, transitionListener);
t02.addEventListener(TransitionEvent.INIT, transitionListener);
t02.addEventListener(TransitionEvent.COMPLETE, transitionListener);
t21.addEventListener(TransitionEvent.INIT, transitionListener);
t21.addEventListener(TransitionEvent.COMPLETE, transitionListener);
t10.addEventListener(TransitionEvent.INIT, transitionListener);
t10.addEventListener(TransitionEvent.COMPLETE, transitionListener);
function stateListener(e:StateEvent):void {
switch (e.type) {
case StateEvent.ENTER:
trace("State entered: " + e.state.name);
break;
case StateEvent.EXIT:
trace("State left: " + e.state.name);
break;
}
}
function transitionListener(e:TransitionEvent):void {
switch (e.type) {
case TransitionEvent.INIT:
trace("Transition started: " + e.transition.name);
break;
case TransitionEvent.COMPLETE:
trace("Transition completed: " + e.transition.name);
break;
}
}Feeding The Finite State Machine Inputs
A finite state machine's input is fed through the FSMachine.input() method.
If a current state is an origin state for a transition with corresponding input equal to the parameter passed to the FSMachine.input() method, the finite state machine will follow this transition to a new state.
//note that the finite state machine is initially in the "s0" state
trace("===============");
//triggers the transition "t01" from state "s0" to state "s1"
fsm.input("forward");
trace("===============");
//triggers the transition "t12" from state "s1" to state "s2"
fsm.input("forward");
trace("===============");
//triggers the transition "t20" from state "s2" to state "s0"
fsm.input("forward");
trace("===============");
//triggers the transition "t02" from state "s0" to state "s2"
fsm.input("backward");
trace("===============");
//triggers the transition "t21" from state "s2" to state "s1"
fsm.input("backward");
trace("===============");
//triggers the transition "t10" from state "s1" to state "s0"
fsm.input("backward");
trace("===============");The output message is as follows.
===============
State left: s0
Transition started: t01
Transition completed: t01
State entered: s1
===============
State left: s1
Transition started: t12
Transition completed: t12
State entered: s2
===============
State left: s2
Transition started: t20
Transition completed: t20
State entered: s0
===============
State left: s0
Transition started: t02
Transition completed: t02
State entered: s2
===============
State left: s2
Transition started: t21
Transition completed: t21
State entered: s1
===============
State left: s1
Transition started: t10
Transition completed: t10
State entered: s0
===============