Programming game AI(FiniteStateMachine) by (as3)Example
Contents
[ hide ]
Example:
First off,let's overview this simple as3-based Finite State Machine System:
1.IState;
2.IFiniteStateMachine;
3.Agent;
Next,how to construct Finite State Machine(FSM) using AS3?
Code snippet:
IState;
/**
* Each state implements the IState interface.
* Each state implements enter and exit metheod
* for one-off action that the agent takes
* when entering and leaving the state,
* in addition to the update method
* which is run repeatedly while in the state.
* The time parameter in the update method
* is the duration of the frame we're excuting.
*
* @author Knight.zhou
*
*/
public interface IState
{
/**
*
* @param value is the description of monster's state.
*
*/
function set description(value:String):void;
function get description():String;
function enter():void;//called on entering the state
function exit():void;//called on leaving the state
function update(time:Number=0):void;//called every frame while in the state
}
IFiniteStateMachine
/**
* Our FiniteStateMachine must implment this interface.
*
* @author Knight.zhou
*
*/
public interface IFiniteStateMachine
{
function set globalState(s:IState):void;
function get globalState():IState;
function set currentState(s:IState):void;
function get currentState():IState;
function set previousState(s:IState):void;
function get previousState():IState;
function set nextState(s:IState):void;
function get nextState():IState;
}
Agent;
/**
* The agent uses an instance of the FiniteStateMachine class the handle its AI.
* The agent class is a lot more manageable without the FSM implementation
* and all the states inside it. and must have a single FSM class
* that can be used by all agents(who)can even share states across agents too.
*
* @author Knight.zhou
*
*/
public class Agent
{
private var fsm:FiniteStateMachine;
public var name:String = "unnamed";
public var carrier:SWFLoader;
public var traceTarget:TextArea;
/**
*
* @param the name of agent;
* @param the carrier of agent;
* @param the agen's traceTarget;
*
*/
public function Agent(name:String,carrier:SWFLoader,traceTarget:TextArea=null)
{
fsm = new FiniteStateMachine(this);
this.name = name;
this.carrier = carrier;
this.traceTarget = traceTarget;
}
public function update():void
{
fsm.update();
}
public function getFSM():FiniteStateMachine
{
return fsm;
}
}
Supplmentary interpretation
Custom state class implement sample:
FiniteStateMachine
/**
* The FiniteStateMachine is responsible for
* managing the current state.
*
* Add a number of features to the FSM class to
* all chaining of states and returning to previous states.
*
* @author Knight.zhou
*
*/
public class FiniteStateMachine implements IFiniteStateMachine
{
private static const LOG:ILogger = LogUtil.getLogger(FiniteStateMachine);
private var _globalState:IState;//For globally track monster's state.
private var _currentState:IState;
private var _previousState:IState;
private var _nextState:IState;
protected var owner:Agent;
public function FiniteStateMachine( owner:Agent,
currentState:IState=null,
previousState:IState=null,
nextState:IState=null
)
{
this.owner = owner;
this.currentState = currentState;
this.previousState = previousState;
this.nextState = nextState;
}
/**
* Prepare a global state for globally tracking current state.
*
* @param s is anew state;
*
*/
public function set globalState( s:IState ):void
{
_globalState = s ;
}
public function get globalState():IState
{
return _globalState;
}
/**
* Prepare a state for using the current state.
*
* @param s is anew state;
*
*/
public function set currentState( s:IState ):void
{
_currentState = s ;
}
public function get currentState():IState
{
return _currentState;
}
/**
* Prepare a state for use after the current state.
*
* @param s is anew state;
*
*/
public function set nextState( s:IState ):void
{
_nextState = s ;
}
public function get nextState():IState
{
return _nextState;
}
/**
* Prepare a state for use before the current state.
*
* @param s is anew state;
*
*/
public function set previousState( s:IState ):void
{
_previousState = s ;
}
public function get previousState():IState
{
return _previousState;
}
/**
* Update the FSM.
*/
public function update():void
{
if(currentState)
{
currentState.update();
}
}
/**
* Change to another state.
*
* @param s is anew state.
*
*/
public function changeState( s:IState ):void
{
LOG.info("exited:{0}",currentState);
currentState.exit();
previousState = currentState;
globalState = s;
currentState = s;
currentState.enter();
LOG.info("entered:{0}",currentState);
}
/**
* Go to the previous state.
*/
public function goToPreviousState():void
{
changeState( previousState );
}
/**
* Go to the next state.
*/
public function goToNextState():void
{
changeState( nextState );
}
SadLow
/**
* Monster's all kinds of talk states
*
* @author Knight.zhou
*
*/
public class SadLow implements IState
{
private var agent:Agent;
//----------------------------------
// description(native)
//----------------------------------
private var _description:String = "STATE_SAD_LOW";
public function get description():String
{
return _description;
}
public function set description(value:String):void
{
_description = value;
}
public function SadLow(monster:Agent)
{
this.monster = monster;
}
public function enter():void
{
//TODO: implement function
}
public function exit():void
{
//TODO: implement function
}
public function update(time:Number=0):void
{
//TODO: implement function
}
}
Supple Interpretation
XMLFiniteStateMachine
<?xml version="1.0" ?>
<fsm name="XML FiniteStateMachine">
<states>
<state name="stateName">
<transition input="someInputValue" trigger="triggerName" source="head" next="nextTransition"/>
</state>
</states>
</fsm>
This page is wiki editable click here to edit this page.