Vamos a hacer un contador de tiempo inverso. Al hacer un click en el fondo se inicializa el contador, que se puede poner en pausa haciendo otro click en el fondo. Haciendo otro click m·s se vuelve a arrancar
Podeis encontrar una explicaciÛn muy completa de en quÈ consiste el patrÛn MVC aquÌ
B·sicamente, se trata de dividir la aplicaciÛn en tres capas. El modelo, son los datos o la lÛgica de la aplicaciÛn, la vista el interfaz, y el controlador el encargado de unir uno y otro, es decir, de actualizar los datos cuando se manipula el interfaz, y de actualizar el interfaz cuando cambian los datos.
En nuestro caso, el modelo es una clase AS2 que es la encargada de llevar la cuenta del tiempo. A cada segundo, emite un evento, que recibe el controlador, que a su vez, se encargar· de actualizar la vista, que es un campo de texto donde se presenta el tiempo restante. Cuando se hace un click en el fondo, la vista comunica el click al controlador, que a su vez, comunica al modelo que debe cambiar su estado (para si estaba arrancado, o arrancar si estaba parado).
Aprovechamos que el orden de carga ( configuraciÛn de publicaciÛn ) del swf es de abajo a arriba, para instanciar el controlador en la primera capa del primer frame , y la vista en la segunda capa del primer frame.
Para instanciar el controlador:
import net.designnation.patterns.*
var myController: controller = new controller( this );
myController.init( 60 );
El controlador tiene agregado una instancia del modelo, de manera que en el modelo se instancia en el mÈtodo init( ) del controlador :
public function init( time: Number )
{
this.myClock = new clock( this.timeline, time );
this.myClock.addEventListener( "endOfTime", this );
this.myClock.addEventListener( "updateTime", this );
this.myClock.init( );
}
De este modo, se instancia la clase clock, pas·ndola como par·metros una referencia al _root, y el tiempo total. Esa referencia al _root se utiliza para crear un clip vacÌo, en cuyo onEnterFrame se decrementa el tiempo total.
public function init( )
{
this.clockClip = timeline.createEmptyMovieClip( "empty",
this.timeline.getNextHighestDepth( ) );
this.clockClip[ "owner" ] = this;
this.clockClip.onEnterFrame = function ( )
{
if ( this[ "owner" ].workingFlag )
{
if ( this[ "owner" ].actualTime>= 1 )
{
this[ "owner" ].actualTime--;
if ( this[ "owner" ].actualTime % FRAMERATE == 0 )
{
this[ "owner" ].dispatchTime( this[ "owner"].actualTime );
}
}
else
{
this[ "owner" ].dispatchTime( );
delete this.onEnterFrame;
}
}
}
}
Observemos la sintaxis de la lÌnea
this.clockClip[ "owner" ] = this;
Es lo mismo que escribir
this.clockClip.owner = this;
El hecho de meter "owner" entre corchetes es tan sÛlo para identificar esa propiedad con un vistazo como una propiedad que he creado din·micamente.
Por tanto, es una de las convenciones que yo utilizo, no tiene mayor significado.
Como puede verse, cuando hace falta actualizar el campo de texto con el tiempo restante, la instancia de clock dispara un evento
private function dispatchTime( actualTime: Number )
{
if ( actualTime == null )
{
var event = "endOfTime";
}
else
{
var event = "updateTime";
}
this.dispatchEvent( {type: event, target: this, time: ( actualTime/ FRAMERATE ) } );
}
Como el controlador est· registrado como listener de clock, se ejecuta el mÈtodo correspondiente:
public function updateTime( arg: Object )
{
this.timeline.clock.text = arg.time;
}
que es el que se encarga de actualizar la vista.
En sentido contrario, la lÛgica es parecida, salvo que se ejecutan directamente los mÈtodos p˙blicos correspondientes ( que, en realidad deberÌan formar parte de un interfaz de comunicaciÛn, pero eso ya es complicarnos demasiado por hoy ).
Cuando se hace click en el fondo,
this.onMouseUp = function( )
{
myController.changeClockState( "clock" );
}
Y en el controlador:
public function changeClockState( )
{
this.myClock.changeClockState( );
}
Y finalmente, en la clase clock:
public function changeClockState( )
{
this.workingFlag = !this.workingFlag;
}
Resumiendo, todas las comunicaciones en uno u otro sentido se har·n a travÈs del controlador. De ese modo, aseguramos la independencia entre la parte gr·fica de la aplicaciÛn y los datos de la misma, y por tanto nuestra aplicaciÛn ser· m·s modular, m·s f·cil de mantener, de modificar, nuestro cÛdigo estar· m·s estructurado, ....
Por otra parte, podeis ver cÛmo la vista no est· estructurada como clase AS2, ya que no parece necesario hacerlo. Es una de las cosas que me encantan de flash. Podemos mezclar cÛdigo en uno u otro estandar, dependiendo de lo que nos interese en cada momento....
Descarga el cÛdigo fuente y el fla aquÌ