Pixlib - Tut 03 - How to load assets at runtime

readed 4742 times

Hello there.

As said in the title this tutorial will help you to load assets at runtime. At the same time we will see how to use FlashDevelop and MTASC to create a swf. So no need to open flash anymore...

Ok first, if you didn't please look at the first tutorial which give you the basis of the pixlib framework.

This tutorial will use the source files of the first tutorial as a starting point. You can download those files from here

First Tutorial Sources Download the first tutorial sources (Size: 49.8 KB)

The sources of this tutorial
Tutorial Sources Download this tutorial's sources (Size: 162.6 KB)

 

I. Refreshing our memory

So remember, we had a fla importing the Application.as class and then creating an instance of it to start the whole application.

Actionscript:
  1. import net.webbymx.projects.tutorial01.Application;
  2. var apz : Application = new Application( this );

The fla had the assets in it's library so we were doing in the Application.as

Actionscript:
  1. //  Instantiating the views
  2.     var digital : MovieClip = this.attachMovie("mc_digital", "mc_digital", 0 );
  3.     var vDigital  : ViewDigital = new ViewDigital ( digital );

to instantiate a view.

 

II. SWFMILL and MTASC

Now, we don't want to use flash anymore ( anyway for the development side ).

We will use 2 tools:

  • SWFMILL to create swfs ( empty or not, see the project page for more info please )
  • MTASC to compile our classes with and push them in the swf created by SWFMILL

If you don't know how to use or integrate those great tools to your editor, go on their respective project page and / or on the project page of your editor.

For my case, I'm using FlashDevelop a great FREE editor ( only for window user sorry :/ ). It has MTASC and SWFMILL in it, and it's as simple as clicking a button to compile your project.

 

III. Show me the sh*t!!!

Ok, ok...

a. Pixlib Classes used

We will use 3 classes that are part of the Pixlib framework.

  • The first one is the ConfigLoader, which helps you loading the XML setting up your application
  • The second one is the GraphicLib, which helps you loading an asset in your application.
  • The third one is the LibStack, which is a download manager

Why that?
First we need to load an xml to know where our assets are.
Then we will use the LibStack, push in it all the GraphicLib created ( one for each asset ) and start the download process.

By the way if you dunno how works the ConfigLoader class have a look here please.

b. A typical Application.as

Here is the code of a typical Application.as class. I'm now always using this as a template for all my projects ( until further improvement as usual :) )
It's a bit long, but it's just for you to have a quick look. We will go anyway in details in the code...

Actionscript:
  1. //  Debug
  2. import com.bourre.log.Logger;
  3. import com.bourre.log.LogLevel;
  4. import com.bourre.log.PixlibDebug;
  5. import com.bourre.utils.LuminicTracer;
  6.  
  7. //  Models
  8. import com.bourre.core.Model;
  9. import net.webbymx.projects.tutorial03.models.*;
  10.  
  11. //  Views
  12. import com.bourre.visual.MovieClipHelper;
  13. import net.webbymx.projects.tutorial03.views.*;
  14.  
  15. //  Controller
  16. import net.webbymx.projects.tutorial03.commands.Controller;
  17.  
  18. //  Personnal EventBroadcaster
  19. import net.webbymx.projects.tutorial03.events.XEventBroadcaster;
  20.  
  21. //  Events
  22. import com.bourre.events.BasicEvent;
  23. import com.bourre.events.IEvent;
  24. import net.webbymx.projects.tutorial03.events.EventList;
  25.  
  26. //  ConfigLoader
  27. import com.bourre.data.libs.ConfigLoader;
  28. import com.bourre.data.libs.XMLToObjectDeserializer;
  29.  
  30. //  Libstact, GraphicLib
  31. import com.bourre.data.libs.LibStack;
  32. import com.bourre.data.libs.GraphicLib;
  33. import com.bourre.data.libs.GraphicLibEvent;
  34.  
  35. //  tweening
  36. import com.mosesSupposes.fuse.*;
  37.  
  38. class net.webbymx.projects.tutorial03.Application
  39.     extends MovieClip {
  40.        
  41. /* ****************************************************************************
  42. * PRIVATE STATIC VAR
  43. **************************************************************************** */
  44.     private static var _oI  : Application;
  45.    
  46.  
  47. /* ****************************************************************************
  48. * PRIVATE VARIABLES
  49. **************************************************************************** */
  50. //  VAR
  51.     private var _oConf  : Object
  52.  
  53.    
  54. /* ****************************************************************************
  55. * CONSTRUCTOR
  56. **************************************************************************** */
  57.     private function Application(container) {
  58.     //  the movieclip is transtyped as a application object
  59.         container.__proto__ = this.__proto__;
  60.         container.__constructor__ = Application;
  61.         this = container;
  62.         _oI = this;
  63.        
  64.     //  init the object
  65.         _init();
  66.        
  67.     //  load the conf
  68.         _loadConf();
  69.     }
  70.    
  71.     public static function getInstance() : Application {
  72.         if ( _oI == undefined ) {
  73.             if ( arguments[ 0 ] == undefined || typeof( arguments[ 0 ] ) != "movieclip" ) PixlibDebug.FATAL( "Cannot create the Application object. You need to pass a MovieClip as a parameter" );
  74.             else var apz : Application = new Application( arguments[ 0 ] );
  75.         }
  76.         return _oI;
  77.     }
  78.    
  79.     public static function main( mc : MovieClip ) : Void {
  80.         var apz : Application = Application.getInstance( mc );
  81.     }
  82.    
  83.  
  84. /* ****************************************************************************
  85. * PRIVATE FUNCTIONS
  86. **************************************************************************** */
  87. /**
  88. * Init the Application
  89. * @param    Void
  90. */ 
  91.     private function _init() : Void {
  92. Logger.LOG( "Application :: _init" );
  93.  
  94.         Stage.align = "TL";
  95.  
  96.     //  register the ZigoEngine
  97.         ZigoEngine.register( PennerEasing, FuseItem, FuseFMP );
  98.         ZigoEngine.EASING = "linear";
  99.        
  100.     //  init the debugger
  101.         Logger.getInstance().addLogListener( LuminicTracer.getInstance() );
  102.        
  103.     //  create the model
  104.         var mClock : ModelClock = new ModelClock();
  105.  
  106.     //  init the controller with our custom EventBroadcaster class
  107.         Controller.getInstance( XEventBroadcaster.getInstance() );
  108.     }
  109.  
  110.    
  111. /**
  112. * Load the congif.xml file
  113. * @param    Void
  114. */
  115.     private function _loadConf( Void ) : Void {
  116. Logger.LOG( "Application :: _loadConf" );
  117.  
  118.     //  Define some properties of the deserializer
  119.         XMLToObjectDeserializer.DESERIALIZE_ATTRIBUTES = true;
  120.         XMLToObjectDeserializer.PUSHINARRAY_IDENTICAL_NODE_NAMES = true;
  121.        
  122.     //  creating the object holding the result for a map
  123.         _oConf = new Object();
  124.    
  125.     //  creating the config loader
  126.         var _cfLoader : ConfigLoader = new ConfigLoader( _oConf );
  127.     //  define the callback once the xml is loaded
  128.         _cfLoader.addEventListener( ConfigLoader.onLoadInitEVENT, this, loadLoader );
  129.     //  load by default the "config.xml" file
  130.         _cfLoader.load();
  131.     }
  132.  
  133.  
  134.     public function _loadAssets () : Void {
  135. Logger.LOG( "Application :: loadAssets" );
  136.  
  137.     //  total bytes loaded
  138.         var totalBytes : Number = 0;
  139.        
  140.     //  Loading everything
  141.         var libContainer : MovieClip = this["__libContainer"];
  142.         var libs : LibStack = new LibStack();
  143.    
  144.     //  get the array of assets to load
  145.         var aAssets : Array = _oConf.assets.asset;
  146.         for( var i = 0; i <aAssets.length; ++i ) {
  147.         //  create the graphic lib
  148.             var gl : GraphicLib = new GraphicLib( libContainer, aAssets[ i ].depth, false );
  149.         //  define callbacks
  150.             gl.addEventListener( GraphicLib.onLoadInitEVENT, this, onAssetLoaded );
  151.             gl.addEventListener( GraphicLib.onLoadProgressEVENT, this, onAssetProgress );
  152.         //  add to the LibStack
  153.             libs.enqueue( gl, aAssets[ i ].view, _oConf.paths.assets + aAssets[ i ].url );
  154.         //  update the totalBytes
  155.             totalBytes += aAssets[ i ].size;
  156.         }
  157.        
  158.     //  set the total bytes
  159.         var vLoader : ViewPreloader = ViewPreloader( MovieClipHelper.getMovieClipHelper( ViewList.VIEW_PRELOADER ) );
  160.         vLoader.setTotalBytes( totalBytes );
  161.  
  162.     //  define the call back events
  163.         libs.addEventListener ( LibStack.onLoadCompleteEVENT, this );
  164.         libs.addEventListener( LibStack.onTimeOutEVENT, this );
  165.  
  166.     //  Start the download
  167.         libs.execute();
  168.     }
  169.  
  170. /**
  171. * Build the Application
  172. * @param    Void
  173. */
  174.     private function _build( Void ) : Void {
  175. Logger.LOG( "Application :: _build" );
  176.    
  177.     //  you can hide the preloader from inside a command ( like in a command StartApplication )
  178.         var vLoader : ViewPreloader = ViewPreloader( MovieClipHelper.getMovieClipHelper( ViewList.VIEW_PRELOADER ) );
  179.         vLoader.fadeout();
  180.  
  181.     //  create views
  182.         var vDigital  : ViewDigital = new ViewDigital ( ViewList.VIEW_DIGITAL );
  183.         var vAnalog  : ViewAnalog = new ViewAnalog ( ViewList.VIEW_ANALOG );
  184.         var vTools : ViewTools = new ViewTools ( ViewList.VIEW_TOOLS );
  185.  
  186.     //  views listening to the model
  187.         var mClock : ModelClock = ModelClock( Model.getModel( ModelList.MODEL_CLOCK ) );
  188.         mClock.addListener( vDigital );
  189.         mClock.addListener( vAnalog );
  190.         mClock.addListener( vTools );
  191.  
  192.     //  The clock start playing
  193.         XEventBroadcaster.getInstance().broadcastEvent( new BasicEvent( EventList.START_CLOCK ) );
  194.     }
  195.    
  196.  
  197. /* ****************************************************************************
  198. * PUBLIC FUNCTIONS - CALLBACKS
  199. **************************************************************************** */
  200. /**
  201. * load the loader ( funny :/ )
  202. * @param    e
  203. */
  204.     public function loadLoader( e : IEvent ) : Void {
  205. Logger.LOG( "Application :: loadAssets" );
  206.     //  this movieclip will be the main container for all the assets loaded
  207.         var libContainer = createEmptyMovieClip( "__libContainer" , this.getNextHighestDepth() );
  208.    
  209.     //  Creating the GraphicLib for the prelaoder
  210.         var gl : GraphicLib = new GraphicLib( libContainer, _oConf.assets.preloader.depth, false );
  211.     //  define the callbacks
  212.         gl.addEventListener( GraphicLib.onLoadInitEVENT, this, onLoaderLoaded );
  213.     /*  define the name of the library - the same as the view name
  214.     *   thus when we are creating the view, the view will look in all the GraphicLib will find one
  215.     *   with the same name and will use it */
  216.         gl.setName( _oConf.assets.preloader.view );
  217.     //  load the preloader
  218.         gl.load( _oConf.paths.assets + _oConf.assets.preloader.url );
  219.  
  220.     }
  221.    
  222. /**
  223. * call back once the graphic of the laoder is called
  224. * @param    e
  225. */
  226.     public function onLoaderLoaded( e : GraphicLibEvent ) : Void {
  227. Logger.LOG( "Application :: onLoaderLoaded" );
  228.     //  create the view, will link automatically to the graphic
  229.         var vLoader : ViewPreloader = new ViewPreloader( e.getName() );
  230.         vLoader.show();
  231.        
  232.     //  start the download process
  233.         _loadAssets();
  234.     }
  235.  
  236.  
  237. /**
  238. * Update the loader view
  239. * @param    e
  240. */
  241.     public function onAssetProgress( e : GraphicLibEvent ) : Void {
  242.         var vLoader : ViewPreloader = ViewPreloader( MovieClipHelper.getMovieClipHelper( ViewList.VIEW_PRELOADER ) );
  243.         vLoader.onLoadProgress( e.getLib().getBytesLoaded() );
  244.     }
  245.    
  246.    
  247. /**
  248. * Update the loader view
  249. * @param    e
  250. */
  251.     public function onAssetLoaded ( e : GraphicLibEvent ) : Void  {
  252. Logger.LOG( "Application :: onAssetLoaded : " + e.getName() );
  253.     //  e.getView().stop();
  254.         var vLoader : ViewPreloader = ViewPreloader( MovieClipHelper.getMovieClipHelper( ViewList.VIEW_PRELOADER ) );
  255.         vLoader.addBytes( e.getLib().getBytesTotal() );
  256.     }
  257.  
  258. /**
  259. * Once everything is loaded
  260. */
  261.     public function onLoadComplete() : Void {
  262. Logger.LOG( "Application :: onLoadComplete" );
  263.         _build();
  264.     }
  265.  
  266. /* ****************************************************************************
  267. * GETTER & SETTER
  268. **************************************************************************** */
  269. }

Ok let's see the code in details now.

As usual my Application.as when created is calling the _init() function, which is setting up ( here ) the fuse tween engine, the Looger, and controller using our custom EventBroadcaster ( why using a custom EventBroadcaster is explain in the first tutorial )

LOADING THE CONFIGURATION
Then following the process said above, I'm first loading the config.xml file

Actionscript:
  1. /**
  2. * Load the congif.xml file
  3. * @param    Void
  4. */
  5.     private function _loadConf( Void ) : Void {
  6. Logger.LOG( "Application :: _loadConf" );
  7.  
  8.     //  Define some properties of the deserializer
  9.         XMLToObjectDeserializer.DESERIALIZE_ATTRIBUTES = true;
  10.         XMLToObjectDeserializer.PUSHINARRAY_IDENTICAL_NODE_NAMES = true;
  11.        
  12.     //  creating the object holding the result for a map
  13.         _oConf = new Object();
  14.    
  15.     //  creating the config loader
  16.         var _cfLoader : ConfigLoader = new ConfigLoader( _oConf );
  17.     //  define the callback once the xml is loaded
  18.         _cfLoader.addEventListener( ConfigLoader.onLoadInitEVENT, this, loadLoader );
  19.     //  load by default the "config.xml" file
  20.         _cfLoader.load();
  21.     }

You should know this already, otherwise go look the second tutorial

LOADING THE LOADER
So when our config.xml is loaded the function loadLoader is called

Actionscript:
  1. /**
  2. * load the loader ( funny :/ )
  3. * @param    e
  4. */
  5.     public function loadLoader( e : IEvent ) : Void {
  6. Logger.LOG( "Application :: loadAssets" );
  7.     //  this movieclip will be the main container for all the assets loaded
  8.         var libContainer = createEmptyMovieClip( "__libContainer" , this.getNextHighestDepth() );
  9.    
  10.     //  Creating the GraphicLib for the prelaoder
  11.         var gl : GraphicLib = new GraphicLib( libContainer, _oConf.assets.preloader.depth, false );
  12.     //  define the callbacks
  13.         gl.addEventListener( GraphicLib.