The State pattern and game development ( III )
So, it's time for some code.
You can download the code here. But you should take a look also at the linked list and hashmap we published some time ago, because we will need them now.
We have implemented four classes
Transition ( transitions )
State ( states )
SMachine ( state machine )
BEngine( behaviour engine, it's the one that manages all the game's state machines )
Things will work the following way: first we'll create the state machine that we are going to need, then we'll add it its states and transitions, and then we'll register that state machine in the global behaviour engine ( BEngine ). That behaviour engine will have a timer, so it will control the state machines execution.
First, we'll take a look at this engine. To simplify, it's just a list that holds a reference to each state machine that has been registered. So we can add new state machines to that list, remove a machine from it…
class BEngine
{
private var machineListVal: List;
public function BEngine( )
{
this.machineListVal= new List( );
}
public function registerSMachine( machine: SMachine )
{
this.machineListVal.push( machine );
}
public function unregisterSMachine( machine: SMachine )
{
this.machineListVal.deleteElement( machine );
}
public function doProcess( )
{
var it: IIterator= this.machineListVal.iterator( );
while( it.hasNext( ) )
{
SMachine( it.next( ) ).executeCycle( );
}
}
}
The state machine is not a collection with all the states and transitions. However, we hold only a reference to the first state and the current state. Why? Because the states will be linked by the transitions, so we don't need to know all the states of the state machine, only the first one, and the current one ( so we can evaluate its transitions). However, we have to know if the machine is running, or is stopped.
class SMachine
{
.
.
.
.
public function resetToInit( initState: State )
{
this.currStateVal = initState;
this.initStateVal= initState;
}
.
.
.
.
}
Each state will hold a callback and an array with a reference to all the transitions that start at that state
class State
{
.
.
.
.
public function addTransition( transition: Transition )
{
if( transitionDoNotExist( transition ) )
{
this.transitions.push( transition );
}
}
.
.
.
public function evalState( paramater: Object ): fgPair
{
var nextState: State= undefined;
var retPair: Pair;
var nTam: Number= this.transitions.length;
for( var nIx: Number= 0; nIx< nTam && nextState== undefined; nIx++ )
{
var currentTransition: Transition= this.transitions[ nIx ];
if( currentTransition.evaluate( ) )
{
if( this.__traceInfo__ )
{
trace( "TRANSIT:"+ this.id+ "->"+ currentTransition.endState.id+ " BY "+ currentTransition.id );
}
nextState= currentTransition.endState;
retPair = new fgPair( nextState, currentTransition );
}
}
return retPair;
}
public function execute( parameter: Object ): Object
{
if( this.__traceInfo__ )
{
trace( "S[A]:"+ this.id+"; "+ this.actionCallbackVal.callbackMethod );
}
return actionCallbackVal.fire( parameter );
}
.
.
.
.
}
And last, the transitions. Each transition holds a reference to the initial and the final state and has the ability to execute a callback
class Transition
{
.
.
.
public function set initState( state: State )
{
state.addTransition( this );
this.initStateVal= state;
}
public function set endState( state: State )
{
this.endStateVal= state;
}
.
.
.
public function execute( parameter: Object ): Object
{
if( this.__traceInfo__ )
{
trace( "T[A]:"+ this.id+"; "+ this.actionCallbackVal.callbackMethod );
}
return this.actionCallbackVal.fire( parameter );
}
public function evaluate( ): Boolean
{
var retVal: Boolean= true;
if( this.evaluationCallbackVal!= undefined )
{
retVal= Boolean( evaluationCallbackVal.fire( this ) );
}
return retVal;
}
.
.
.
}
Well, now it's time or an example. But that will be in another post.
Comentarios
Thank You, I have found a lot of useful info in these your three last posts. Moreover, there's much more foods for my mind rather than just information.
Best Regards!
Rost
Publicado por: Rostislav Siryk | July 12, 2004 11:23 AM
Thanks, Rostislav, that is really nice.
Publicado por: Cesar Tardaguila | July 12, 2004 08:52 PM