El patrÛn State aplicado al desarrollo de juegos ( III )
Ya ha llegado el momento de empezar a ver cÛdigo.
Puedes bajarte el cÛdigo aquÌ. Nos apoyamos tambiÈn en las implementaciones de lista enlazada y en la de HashMap
Hemos implementado la m·quina de estados utilizando cuatro clases
:
Transition ( transiciones )
State ( estados )
SMachine ( mq·uina de estados )
BEngine( motor de comportamientos, es quien maneja las m·quinas de estados )
B·sicamente el procedimiento ser· el siguiente: se crear· la m·quina de estados de la entidad correspondiente, se le aÒadir·n los estados y transiciones necesarias, y m·s tarde se registrar· esa m·quina en el motor global de la aplicaciÛn. Ese motor ser· el encargado de mandar a las m·quinas de estados que tenga registradas que ejecuten el paso siguiente.
Veamos primero la estructura de ese motor. B·sicamente no es m·s que una lista enlazada en la que guardamos todas las m·quinas de estados que registremos, y mÈtodos para registrar m·quinas de estados, eliminarlas del registro, y darlas la orden de proceso.
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( );
}
}
}
La m·quina de estados no la hemos implementado como una colecciÛn de estados y transiciones, sino que sÛlo guardamos una referencia al primer estado, y al estado actual en que se encuentre. Como ya las transiciones relacionan los estados entre sÌ, no tenemos necesidad de conocer todos los estados y transiciones desde la propia m·quina de estados, sino que con conocer el primero es suficiente. Lo que sÌ que tiene que controlar esta clase es si la m·quina de estados est· arrancada, o parada
class SMachine
{
.
.
.
.
public function resetToInit( initState: State )
{
this.currStateVal = initState;
this.initStateVal= initState;
}
.
.
.
.
}
Cada estado tendr· asociado un callback ( que es el que va a ejecutar cuando la m·quina de estados entre en ese estado, y un array con las transiciones que salen de Èl.
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 );
}
.
.
.
.
}
Y por fin, las transiciones. Cada transiciÛn tiene una referencia al estado inicial y al final, asÌ como la capacidad de ejecutar el callback que se le pase.
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;
}
.
.
.
}
Pues ya sÛlo falta implementar un ejemplo de utilizaciÛn. Pero eso ser· otro dÌa.