Asset Management

Overview

Every game or application needs certain assets — be it textures, sounds, bitmap fonts, or various other objects. Those assets can be either embedded (which makes sense for browser games to have everything in one file) or files accompanying the game (good for mobile games to save the RAM required by embedded objects).

The big number of options in how to reference your assets makes it difficult to access them in a uniform way. The AssetManager helps you with that. It's a class that allows you to add assets in all kinds of ways, and access them easily.

At the moment, the AssetManager supports the following types of assets:

  • Textures (either from Bitmaps or ATF data)
  • Texture atlases
  • Bitmap Fonts
  • Sounds
  • XML data
  • JSON data
  • ByteArrays

To accomplish this, the AssetManager uses a three-step process:

  1. You add pointers to your assets to a queue, e.g. “File” objects.
  2. You tell the AssetManager to process the queue.
  3. As soon as the queue finished processing, you can access all assets with corresponding 'get'-methods.

The AssetManager contains a “verbose” property. If enabled, all steps of the enqueuing and loading process will be traced to the console. Very useful for debugging, or if you don't understand why a certain asset is not showing up! (Beginning with Starling 1.6, that mode is activated by default.)

Enqueuing the Assets

Let's say you want to load a few assets from disk, and load others from an embedded class. The first step is to enqueue references to all those assets.

Assets from disk or from the network

Enqueuing files from URLs or from local paths is rather straight-forward:

// enqueue a file from an URL
assets.enqueue("http://gamua.com/img/home/starling-flying.jpg");
 
// enqueue a file from disk (AIR only)
var appDir:File = File.applicationDirectory;
assets.enqueue(appDir.resolvePath("sounds/music.mp3"));
 
// enqueue all contents of a directory, recursively (AIR only)
assets.enqueue(appDir.resolvePath("textures"));

To embed a texture atlas, just enqueue both its XML file and the corresponding texture. Make sure that the imagePath attribute in the XML file contains the correct filename — because that's what the AssetManager will look for when it creates the atlas later.

assets.enqueue(appDir.resolvePath("textures/atlas.xml"));
assets.enqueue(appDir.resolvePath("textures/atlas.png"));

Bitmap Fonts work just the same. This time, you need to make sure that the file attribute in the XML (the '.fnt'-file) is set up correctly.

assets.enqueue(appDir.resolvePath("fonts/desyrel.fnt"));
assets.enqueue(appDir.resolvePath("fonts/desyrel.png"));

Embedded Assets

For the embedded assets, I recommend you put all the embed statements in a separate class. Declare them as public static const, and follow these naming conventions:

  • Classes for embedded images should have the exact same name as the file, without extension. This is required so that references from XMLs (atlas, bitmap font) won't break.
  • Atlas and Font XML files can have an arbitrary name, since they are never referenced by file name.

Here's a sample of such a class:

public class EmbeddedAssets
{
    /* PNG texture */
    [Embed(source="/textures/bird.png")]
    public static const bird:Class;
 
    /* ATF texture */
    [Embed(source = "textures/1x/atlas.atf", mimeType="application/octet-stream")]
    public static const atlas:Class;
 
    /* XML file */
    [Embed(source="textures/1x/atlas.xml", mimeType="application/octet-stream")]
    public static const atlas_xml:Class;
 
    /* MP3 sound */
    [Embed(source="/audio/explosion.mp3")]
    public static const explosion:Class;
}

When you enqueue that class, the asset manager will later instantiate all of those embedded assets.

var assets:AssetManager = new AssetManager();
 
// enqueues "bird" texture, "explosion" sound and a texture atlas.
assets.enqueue(EmbeddedAssets);

Loading the Assets

Now that the assets are enqueued, you can load all of them at once. That's the part where you should show some kind of progress bar or loading indicator to your users.

assets.loadQueue(function(ratio:Number):void
{
    trace("Loading assets, progress:", ratio);
 
    // -> When the ratio equals '1', we are finished.
    if (ratio == 1.0)
        startGame();
});

Note that the “startGame” method is something you have to implement yourself — that's where you could hide the loading screen and start the actual game.

With enabled “verbose” property, you'll see the names with which the assets can be accessed:

[AssetManager] Adding sound 'explosion'
[AssetManager] Adding texture 'bird'
[AssetManager] Adding texture 'atlas'
[AssetManager] Adding texture atlas 'atlas'
[AssetManager] Adding bitmap font 'desyrel'

Accessing the Assets

Finally: now that the queue finished processing, you can access your assets with the various “get…” methods of the AssetManager. Each asset is referenced by a name, which is the file name of the asset without an extension, or the class name of embedded objects.

// this will first search named textures, then atlases
var texture:Texture = assets.getTexture("bird");
 
// this will look through all named textures and atlases
var textures:Vector.<Texture> = assets.getTextures("animation");
 
// play a sound and receive the SoundChannel that controls it
var explosion:SoundChannel = assets.playSound("explosion");

If you enqueued a bitmap font along the way, it will already be registered and ready to use.

If you want to extend the AssetManager (e.g. to add your own asset types), have a look at this GitHub Post; it contains some sample code that will get you started.


Next section: Memory Optimization

  manual/asset_management.txt · Last modified: 2014/12/02 20:25 by daniel
 
Powered by DokuWiki