Comunidad de diseño web y desarrollo en internet online

Asignar código actionscript en clases a fotogramas concretos

Cuando trabajamos con Flash es probable que montemos la película colocando cada pantalla de la aplicación en un fotograma de la linea de tiempo principal, y que vayamos saltando de fotograma a fotograma para cambiar de pantalla.



Evidentemente cada fotograma tendrá sus gráficos y botones que deberán ejecutar unas funciones. En principio estos códigos deberíamos colocarlos en los fotogramas correspondientes. Quizás para el código no nos interese tener que ir colocándolo fotograma a fotograma sino que queramos trabajarlo a través de clases, y mantener el .fla limpio de código.



Mucha gente al hacer esto se encuentra con el problema que no sabe como escribir y ejecutar funciones a medida vas cambiando de fotograma en la película, o que les salta el típico error de ejecutar las acciones antes de que el fotograma esté disponible.

En este tip mostraré una serie de clases que me sirvieron para hacer esto.

El resultado es que en la clase de la película principal tengo esté código:

Código :

package 
{
   import flash.display.MovieClip;
   import com.zguillez.core.TimelineScript;
   //--------------------------------------------------------------------------------
   public class Main extends MovieClip
   {
      private var _timelineScript:TimelineScript;
      //----------------------------------------------------------------------------
      public function Main()
      {
         _timelineScript = new TimelineScript(this);
         _timelineScript.setFrame( 1, new Frame1(this) );
         _timelineScript.setFrame( 2, new Frame2(this) );
         _timelineScript.setFrame( 3, new Frame3(this) );
         /* etc.. */
         stop();
      }
      //----------------------------------------------------------------------------
   }
}


Como se ve, hay una clase que le llamo TimelineScript que me controla que código hay en cada fotograma, y a la que se le agragan a través de la función setFrame() una serie de clases (Frame1, Frame2, Frame3, etc..) que son las clases que contienen el código para cada fotograma independientemente.

Un ejemplo de clase para manejar un fotograma podría ser este:

Código :

package 
{
   import flash.display.MovieClip;
   import flash.events.MouseEvent;
   import com.zguillez.core.FrameScript;
   //--------------------------------------------------------------------------------
   public class Frame1 extends FrameScript
   {
      //----------------------------------------------------------------------------
      public function Frame1(ruta:MovieClip)
      {
         super(ruta);
      }
      //----------------------------------------------------------------------------
      override protected function actions():void
      {
         var boton:MovieClip = _ruta.getChildByName("bot1") as MovieClip;
         boton.buttonMode = true;
         boton.addEventListener(MouseEvent.CLICK, function()
         {
            gotoFrame(2)
         });
         /* resto del código para este fotograma */
      }
      //----------------------------------------------------------------------------
   }
}


El código para este fotograma lo colocaremos dentro de la función actions(). En este caso únicamente hacemos que un clip llamado "bot1" nos salte la película hasta el fotograma 2. En principio tendríamos una clase como esta para cada fotograma.

Hay que fijarse que esta clase extiende de otra clase llamada FrameScript. Esta clase contiene métodos comunes para todas las clases de fotogramas como la clase actions(), que deberemos sobreescribir desde las clases concretas, y la función pública gotoFrame() que es la que nos cambia de fotograma y que deberemos utilizar en lugar de un gotoAndStop().

Tanto la clase FrameScript como la TimelineScript las tendremos guardadas dentro de nuestro package de clases para reutilizarlas en diferentes proyectos ya que no necesitaremos editarlas para ningún proyecto concreto.

Aquí las vemos:

Código :

package com.zguillez.core
{
   import flash.display.MovieClip;
   import flash.events.Event;
   import com.zguillez.core.TimelineScript;
   //--------------------------------------------------------------------------------
   public class FrameScript
   {
      protected var _ruta:MovieClip;
      private var _timelineScript:TimelineScript;
      //----------------------------------------------------------------------------
      public function FrameScript(ruta:MovieClip)
      {
         _ruta = ruta;
      }
      //----------------------------------------------------------------------------
      internal function set timelineScript(t:TimelineScript):void
      {
         _timelineScript = t;
      }
      //----------------------------------------------------------------------------
      public final function init():void
      {
         _ruta.stage.addEventListener(Event.ENTER_FRAME, iniActions);
      }
      //----------------------------------------------------------------------------
      private final function iniActions(e:Event):void
      {
         if (_ruta.numChildren > 0)
         {
            if (_ruta.getChildAt(0) != null)
            {
               _ruta.stage.removeEventListener(Event.ENTER_FRAME, iniActions);
               actions();
            }
         }
         else
         {   
            _ruta.stage.removeEventListener(Event.ENTER_FRAME, iniActions);         
            actions();
         }
      }
      //----------------------------------------------------------------------------
      protected function actions():void { /* override */ }
      //----------------------------------------------------------------------------
      protected final function gotoFrame(f:uint):void
      {
         _ruta.gotoAndStop(f);
         _timelineScript.update();
      }
      //----------------------------------------------------------------------------
   }
}


Como vemos esta clase, que es de la que extienden todas las clases concretas de fotogramas, contiene una referencia de la ruta en la que están los gráficos y una referencia de la clase TimelineScript que es la que contiene todas las clases concretas de fotogramas.

Esta clase contiene un método actions() que esta vacío ya que este método será sustituido a través de un override desde las clases concretas de fotograma, ya que evidentemente cada clase tendrá sus propias funciones a ejecutar.

También tiene el método gotoFrame() que como he dicho antes es el que nos hace saltar de fotograma. Vemos que esta función contiene el gotoAndStop() y además ejecuta el método update() de la clase TimelineScript.

Las acciones que incluyamos en la función actions() han de ser inicializadas desde el método init(), más concretamente desde el método iniActions().

Como podemos ver hemos utilizado un ENTER_FRAME para realizar la llamada a la función actions(). Esto es debido a que cuando cambiamos de fotograma y ejecutamos un código, este código se ejecuta antes de que los elementos gráficos de dicho fotograma estén disponibles, con lo que cualquier referencia a ellos desde el código (como por ejemplo el getChildByName("bot1")) nos daría el error de que no existen. Con el ENTER_FRAME generemos un bucle de llamadas hasta que reconoce los elementos gráficos del fotograma, en ese momento ejecuta la acción que les asigna el código.

Vista esta clase, nos queda la clase TimelineScript:

Código :

package com.zguillez.core
{
   import flash.display.MovieClip;
   import com.zguillez.core.FrameScript;
   //--------------------------------------------------------------------------------
   public class TimelineScript
   {
      private var _ruta:MovieClip;
      private var _frameScript:Array = new Array();
      //----------------------------------------------------------------------------
      public function TimelineScript(ruta:MovieClip)
      {
         _ruta = ruta;
         initArray();
      }
      //----------------------------------------------------------------------------
      private function initArray():void
      {
         for (var i:uint = 0; i <= _ruta.totalFrames; i++)
         {
            _frameScript.push(void);
         }
      }
      //----------------------------------------------------------------------------
      public function setFrame(n:uint, s:FrameScript):void
      {
         s.timelineScript = this;
         _frameScript[n] = s;
         if (n == _ruta.currentFrame)
         {
            _frameScript[n].init();
         }
      }
      //----------------------------------------------------------------------------
      public function update():void
      {
         _frameScript[_ruta.currentFrame].init();
      }
      //----------------------------------------------------------------------------
   }
}


Esta clase contiene un Array al que le introducimos tantos elementos como fotogramas tiene la línea de tiempo principal.

A este Array le añadiremos las clases de código concreto para cada fotograma en la posición que les corresponda, a través del método setFrame(), tal como vimos en la clase de la película.

Esta clase también contiene una función update() que lo que hace es ejecutar la función init() de la clase que corresponda al fotograma actual y de esta manera ejecutar las funciones correspondientes para dicho fotograma, y como hemos visto anteriormente esta función update() se ejecuta cada vez que cambiamos de fotograma en la película.

Espero que se entienda el proceso y les sea útil ;)

¿Sabes SQL? ¿No-SQL? Aprende MySQL, PostgreSQL, MongoDB, Redis y más con el Curso Profesional de Bases de Datos que empieza el martes, en vivo.

Publica tu comentario

El autor de este artículo ha cerrado los comentarios. Si tienes preguntas o comentarios, puedes hacerlos en el foro

Entra al foro y participa en la discusión

o puedes...

¿Estás registrado en Cristalab y quieres
publicar tu URL y avatar?

¿No estás registrado aún pero quieres hacerlo antes de publicar tu comentario?

Registrate