Encontronazos con ActionScript 3: Embebiendo gráficos y sonidos en tu aplicación

Este artículo es la parte 6 de 6 de la serie Encontronazos con ActionScript 3

embed

En el artículo anterior estuvimos revisando la carga de imágenes externas a nuestra aplicación. Este método es útil y fácil para cargar estos recursos, pero en algunos casos es necesario tener a mano los recursos inmediatamente disponibles. Para ello se hace necesario incluir estas imágenes y recursos adentro del SWF compilado para agilizar el acceso a ellos. En este artículo aprenderemos cómo se hace embed, embedding o embebido de estos recursos.  (Foto por storker)

En particular vamos a incluir imágenes vectoriales en formato SWF, e imágenes bitmap como JPGs, GIFs (no animados) o PNGs. También podemos incluir sonidos en formato MP3. Es posible incluir GIFs animados dentro del juego, pero se requiere de una librería externa, y requiere cierto conocimiento. Esta técnica se tratará al finalizar este artículo.

Embed, embeber, incluir

Para incluir un recurso dentro del código utilizaremos las anotaciones del compilador de Flex. Las anotaciones son líneas especiales de código que no es ActionScript 3 propiamente. Estas líneas son leídas por el compilador de Flex para indicar propiedades especiales de la variable que modifica a continuación.

Cuando embebemos un recurso en el código, ese recurso va a tener un tipo específico que solamente es reconocido cuando utilizamos la librería completa de Flex. Nosotros no queremos incluir toda la librería Flex porque representaría una sobrecarga de código que no vamos a utilizar. Afortunadamente, tanto los bitmaps como los dibujos vectoriales heredan de una clase que sí podemos utilizar: DisplayObject.

Los recursos que utilizaremos son los mismos del anterior artículo: la imagen del gato (cortesía de PDX Sasquatch), la ilustración vectorial de la computadora y el sonido del trueno (cortesía del proyecto RHumphries).

Cómo nos organizamos

Al igual que la vez pasada, crearemos un proyecto en FlashDevelop para Actionscript 3, pero los 3 recursos los colocaremos en la carpeta de fuente src/.

Incluyendo un bitmap

Este es el código que utilizaremos para embeber una imagen. La explicación después del bloque de código:

package {
  import flash.display.MovieClip;
  import flash.display.DisplayObject;
  import flash.events.Event;
  public class HolaMundo extends MovieClip {
    [Embed(source="kitten.jpg")]
    public var imagenClass:Class;
    public function HolaMundo() {
      if (stage) init();
      else addEventListener(Event.ADDED_TO_STAGE, init);
    }
    public function init(e:Event = null) : void {
      removeEventListener(Event.ADDED_TO_STAGE, init);
      var imagen : DisplayObject = new imagenClass();
      addChild(imagen);
    }
  }
}

La película resultante será totalmente similar a la de cargar una imagen. La diferencia está en que si vemos el tamaño en bytes del SWF ha crecido un poco hasta 17Kb. La imagen ahora está adentro del SWF, por lo que no hace falta cargarla de Internet, sino que al terminar de cargar el SWF la imagen estará disponible inmediatamente. La imagen ahora es una clase que instanciamos como DisplayObject y agregamos dentro de la película, por eso el embed va directamente encima de una variable de tipo Class, y usamos el nombre de la variable para instanciar la clase.

Así es como funciona el Embed: la etiqueta de metadatos encima de la variable imagenClass convierte esa variable en una referencia a la clase que representa la imagen. Así que para usar la imagen tenemos que crear un objeto del tipo que apunta la variable, y luego la agregamos al stage. Probablemente si hyas usado otro lenguaje esto te parezca extraño, pero así funciona.

kitten-embed

Incluyendo un dibujo vectorial

A diferencia de la carga desde Internet, uno no embebe el SWF completo, sino que embebe un símbolo del SWF. Para asignar nombres a las películas en Flash es tan sencillo como hacer que las ilustraciones sean MovieClips y asignarles un nombre dentro de las propiedades. También podemos incluir un SWF, para lo cual requeriremos el nombre del símbolo, además de la ubicación del SWF.  Como verán, el SWF puede ser exportado por Flash, o por cualquier otro programa que exporte a SWF (como Illustrator, por ejemplo). El método es el mismo que la imagen:

package {
  import flash.display.MovieClip;
  import flash.display.DisplayObject;
  import flash.events.Event;
  public class HolaMundo extends MovieClip {
    [Embed(source="computer.swf", )]
    public var imagenClass:Class;
    public function HolaMundo() {
      if (stage) init();
      else addEventListener(Event.ADDED_TO_STAGE, init);
    }
    public function init(e:Event = null) : void {
      removeEventListener(Event.ADDED_TO_STAGE, init);
      var imagen : DisplayObject = new imagenClass();
      addChild(imagen);
    }
  }
}

Incluyendo un sonido

Para incluir un sonido utilizaremos un código similar. Haremos el embed encima de una variable de tipo Class, y luego utilizaremos esa variable para instanciar el sonido de ese tipo, convirtiéndolo a Sound.

package {
  import flash.display.Sprite;
  import flash.media.Sound;
  import flash.media.SoundChannel;
  public class HolaMundo extends MovieClip {
    [Embed(source="thunder.mp3")]
    public var soundClass:Class;
    public function HolaMundo() {
      var thunder:Sound = new soundClass() as Sound;
      thunder.play();
    }
  }
}

Incluyendo un GIF animado en Actionscript 3

Por defecto la clase Loader no reproduce GIFs animados. Si uno pone un GIF animado en el Loader, la clase solamente muestra el primer fotograma. Sin embargo, gracias a los buenos oficios de Thibault Imbert tenemos la librería AS3 GIF Player Class, disponible en http://www.bytearray.org/?p=95.

Esta librería lee el formato de un GIF animado y lo reconstruye fielmente dentro de una película SWF. Es capaz de leer un URLRequest, para cargarlo externamente como en el artículo anterior, o cargar un ByteArray, que no es más que un objeto que tiene el contenido de cualquier archivo binario.

Para instalar la librería se descarga la versión más reciente, a la fecha la versión 0.4, y se copia el directorio org al directorio de fuentes de nuestro proyecto (src/). Para este ejemplo utilizaremos el GIF animado que trae esta versión, el archivo diego.gif.

Si queremos embeber un GIF animado en el código tendremos que hacerlo a pie: tendremos que embeber el archivo asignándole un MIME type de “octet-stream” de tal manera de forzar que su tipo sea un ByteArray; si no se especifica esto, el compilador hará que la clase sea un DisplayObject, dando error a la hora de instanciar. Luego haremos una instancia de ese embed y con el GIF Player cargaremos los bytes correspondientes. Notemos que el GIFPlayer es un DisplayObject, así que lo agregaremos de la misma manera que hemos hecho con todos los elementos gráficos anteriores.

package {
  import org.gif.player.GIFPlayer;
  public class HolaMundo extends MovieClip {
    [Embed(source="mygif.gif", mimeType="application/octet-stream")]
    private var gifStream:Class;
    public function HolaMundo() {
      if (stage) init();
      else addEventListener(Event.ADDED_TO_STAGE, init);
    }
    public function init(e:Event = null) : void {
      removeEventListener(Event.ADDED_TO_STAGE, init);
      var gif:ByteArray = new gifStream() as ByteArray;
      var gifPlayer:GIFPlayer = new GIFPlayer();
      gifPlayer.loadBytes(gif);
      addChild(gifPlayer);
    }
  }
}

¡El código resultante es muy grande!

El problema de embeber muchos recursos gráficos es que todos ellos serán anexados dentro del SWF final, por lo que no serían posible mostrar algo mientras se carga toda la película. Para evitar ello podemos mantener el código en un SWF y mandar todos los recursos a otro SWF. De esta manera, cargamos el primero (que suele ser más pequeño y por ende carga rápidamente), y a partir del primero cargamos el segundo.

Esto es una técnica avanzada que aprenderás en el siguiente artículo. Hasta entonces.

Navegar la seriePost anterior en la serie

2 comentarios en “Encontronazos con ActionScript 3: Embebiendo gráficos y sonidos en tu aplicación”

  1. Tuve problemas cargando el sonido, me mostraba un error "unsupported sampling rate (48000Hz)", por lo cual le cambié al sonido la frecuencia a 44.100 con Audacity y funcionó perfecto. Tienes alguna otra solución para esto?

    Por otro lado, para que realizas la importación "flash.media.SoundChannel".

    P.D. los tips de "Encontronazos con ActionScript 3" me sirvió para empezar con FlashDevelop. Muchas gracias.

    1. 44Khz es una buena frecuencia, en realidad más allá de eso estás engordando innecesariamente tu SWF (Recuerda que cada byte es más tiempo esperando a que se termine de descargar tu aplicación).

      Sound.play() devuelve un SoundChannel, y con él puedes modificar el volumen de ese sonido nada más. En el ejemplo no hago más que reproducir el sonido.

      De nada 😉

Deja un comentario