Carga de assets “at runtime” con Flash

22 February, 2010 (15:42) | Alberto Gonzalez | CS4, flash

Últimamente he estado involucrado en un proyecto realizado en Flash principalmente. Una parte importante de este proyecto es que debe tener temas visuales distintos. Cada tema está compuesto de muchos elementos gráficos principalmente movie clips y animaciones. Cada tema estará definido en la biblioteca de un swf por lo que tendremos varios swf y cada uno de ellos contendrá los assets correspondientes a su tema.

Lo que les voy a mostrar en este post es cómo cargar esos swf y acceder a sus elementos de la biblioteca desde la película principal.

Requerimientos

  • Adobe Flash CS4 (http://www.adobe.com/flash)
  • Prerequisitos

  • Estar familiarizado con la terminología de ActionScript 3.0
  • Haber trabajado con Adobe Flash y el manejo de su biblioteca y símbolos
  • Desarrollo

    El escenario es el sig:

  • Crearemos 3 archivos .fla que ejemplificarán los 3 temas
  • Cada .fla tendrá solo dos elementos en la biblioteca exportados para ActionScript
  • Generaremos un .fla adicional que servirá como aplicación principal y desde la cuál se cargará alguno de los otros 3 swf con los assets preparados
  • Por último utilizaremos en la aplicación principal los elementos que se encuentran en la biblioteca del swf cargado
  • Assets_1

    Assets_2
    Assets_3

    Assets_library

    En las imágenes muestro como deberá quedar la biblioteca de los 3 swf que servirán como contenedores de los assets.
    Únicamente coloqué dos elementos (Header, Footer), por motivos del ejemplo, y tienen asociada su clase respectiva desde la biblioteca.

    No es necesario que pongamos contenido en el escenario ya que no mostraremos el swf cargado, solo utilizaremos sus elementos.

    Vamos ahora a crear el fla que servirá como principal y desde donde pondremos unos controles para cargar los assets requeridos.
    main movie
    contenido combo

    Colocamos 3 componentes en el escenario: Una etiqueta, un botón y un combo box. El botón y el combo box tienen como nombres de instancia "botonCarga" y "comboSeleccion" respectivamente.

    El combo tiene los datos mostrados en la imagen colocados desde el Inspector de Componentes por motivos de facilidad en el ejemplo.

    Los 3 componentes se encuentran dentro de un MovieClip que está en el escenario. Ese movie clip tiene de nombre de instancia "selector". Los componentes se encuentran dentro de este clip para después poder quitarlos más fácilmente.

    Ese movie clip tiene el sig código en la línea de tiempo:

    //ActionScript 3.0
     
    comboSeleccion.addEventListener(Event.CHANGE, onComboChange);
    botonCarga.addEventListener(MouseEvent.CLICK, onBotonClick);
     
    botonCarga.enabled = false;
     
    function onComboChange (event:Event):void 
    {
    	botonCarga.enabled = event.target.selectedIndex > 0;
    }
    function onBotonClick(event:MouseEvent):void
    {
    	MovieClip(parent).cargarAssets(comboSeleccion.selectedItem.data);
    }

    Como se darán cuenta la carga la hace una función llamada "cargarAssets" que se encuentra en la línea de tiempo principal, es decir, el "parent" de este clip. Ahora veamos el código que se encarga de la magia el cual se encuentra en la línea de tiempo principal:

    import flash.utils.getDefinitionByName;
     
    var req:URLRequest = new URLRequest();
    var loader:Loader = new Loader();
    loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onAssetsComplete);
     
    // Esta es la parte importante.
    // El poner las clases cargadas dentro mismo contexto de la aplicación principal
    var lc:LoaderContext = new LoaderContext();
    lc.applicationDomain = ApplicationDomain.currentDomain;
     
    // Esta fn se invoca desde el clip selector
    function cargarAssets (seleccion:String):void 
    {
    	req.url = "assets/" + seleccion;
    	loader.load(req, lc);// Pasándole como segundo argumento el contexto definido arriba
    }
     
    function onAssetsComplete (event:Event):void
    {
    	trace("Assets cargados y disponibles");
     
    	// Definición de las clases a utilizar ( ya están disponibles )
    	// Header y Footer están definidos en la biblioteca del swf cargado
    	var Header:Class = getDefinitionByName("Header") as Class;
    	var Footer:Class = getDefinitionByName("Footer") as Class;
     
    	// Instancias de esas clases
    	var _header:DisplayObject = new Header() as DisplayObject;
    	var _footer:DisplayObject = new Footer() as DisplayObject;
     
    	// Agregamos y acomodamos elementos
    	addChild(_header);
    	addChild(_footer); _footer.y = stage.stageHeight - _footer.height;
     
    	// Ocultamos el componente de selección
    	selector.visible = false;
    }

    El código muestra como carga un swf con la clase Loader. Hasta ahí todo normal. El punto importante es la instancia de "LoaderContext" que está definida justo antes de cargar los elementos y su propiedad applicationDomain. Esa instancia la utilizamos en la función load de la instancia de Loader.

    var lc:LoaderContext = new LoaderContext();
    lc.applicationDomain = ApplicationDomain.currentDomain;

    Un ApplicationDomain es el contexto donde está disponible tu código. Normalmente se genera una instancia de ApplicationDomain por cada swf que tengamos pero con esa instrucción estamos indicando que las classes que contiene el swf de los assets queremos que esten disponibles en el mismo contexto que la película que lo carga, es decir, la película principal.

    Una vez hecho eso, la clase la podemos utilizar como cualquier otra. En el ejemplo estoy obteniendo la definición de las clases "Header" y "Footer" en dos variables que después estoy instanciando y agregando al DisplayList para mostrarlas en la película principal.

    El ejemplo supone que tiene una estructura de archivos similar a la sig:
    - carpeta principal
      - main.swf
      - assets (carpeta)
        - assets_1.swf
        - assets_2.swf
        - assets_3.swf

    Conclusión

    Sabemos que existen las bibliotecas compartidas. Sabemos que podemos tener muchos elementos en la biblioteca y utilizar solo los requeridos pero, sin lugar a dudas, cuando debemos elegir entre varios elementos a cargar para una sola aplicación esta puede ser una de las mejores opciones. De esta forma no incrementan el tamaño de su aplicación principal teniendo assets en la biblioteca que podría no utilizar un usuario, ya sea por su rol asignado o por cualquier otra razón.

    Esta técnica también les puede ayudar a actualizar las aplicaciones, al menos, en cuanto a los elementos gráficos mostrados debido a que con solo cambiar el/los swf de los assets podrán cambiar por completo el diseño de su aplicación.

    Archivos

    Aquí les dejo los archivos del ejemplo (Flash CS4):
    - Carga_Assets.zip

    Espero que les sirva este artículo para sus futuros proyectos.
    Cualquier pregunta no duden en dejar un comentario en el post o enviarme un e-mail a: agonzalez@activ.com.mx

    Comentarios

    Pingback de Carga de assets “at runtime” con Flash | www.riactive.com « Blog de Flash
    Fecha: February 22, 2010, 3:55 pm

    [...] Original post:  Carga de assets “at runtime” con Flash | http://www.riactive.com [...]

    Comentario de bubu
    Fecha: February 22, 2010, 8:17 pm

    Excelente articulo Alberto. Muchas gracias por compartirlo. Sin dudas que es algo muy interesante de utilizar.

    Saludos

    Comentario de Diego Luis Restrepo
    Fecha: June 24, 2010, 9:56 pm

    excelente información, muy útil, quería agregar que tanto el archivo cargado como quien lo carga deben estar en el mismo dominio, o por lo menos solo así fue que me funciono.

    Escribir comentario