Pretty banner! :)

A Class for Managing BitmapDatas

UI Icons

BitmapDatas are a necessary part of a high performance game engine. Sometimes we can get away with haphazard BitmapData management, but more often than not, we need to be aware of where and how we are instantiating BitmapDatas so we can keep track of them and free up memory as appropriate. We also want to make sure we never instantiate two identical BitmapDatas. Today’s article presents a class for managing BitmapDatas which avoids some of the pitfalls associated with using Bitmaps.

Pretty Icons

The Pretty Icons used in the example code are courtesy of icojoy. Thanks guys!

BitmapLibraryManager

The BitmapLibraryManager is the class that we’re going to rely upon to manage our BitmapDatas. It is more capable than simply a BitmapDataManager (yes, this violates the Single Responsibility Principle) but the reality is that it is more useful as a ubiquitous manager tied to specific libraries. Yes, this also means it uses the often abused Singleton Pattern. Ease of use trumped both these (very important) considerations.

There are two ways to register a BitmapData with the BitmapLibraryManager, via registerBitmapData, which simply associates a BitmapData with a name, and via registerBitmapLibrary, which takes an instance of a class whose public properties are Bitmaps, and registers them based on the property name. If you’re unfamiliar with how to embed assets in your AS3 project, take a look at Embedding Assets in an AS3 Only Project. The example in the code project has an IconLibrary that looks something like this:

package
{
public class IconLibrary
{
    [Embed(source='../assets/icons/001_01.png')]
    public const Icon_001_01 : Class;
    [Embed(source='../assets/icons/001_02.png')]
    public const Icon_001_02 : Class;
...
}
}

To register and track all the bitmaps in our IconLibrary, we only need to register it:

BitmapLibraryManager.registerBitmapLibrary( new IconLibrary() );

When we need an instance of a Bitmap, we ask for one from the BitmapLibraryManager:

var myBitmap : Bitmap = BitmapLibraryManager.createBitmap( "Icon_001_01" );

This will guarantee there will only ever be one BitmapData for the associated asset, preventing us from inadvertently instantiating multiple identical versions of expensive memory intensive BitmapDatas.

For some memory metrics, the example code shows off some of memory savings of the BitmapLibraryManager method:

        /* TEST_NAIVE_INSTANTIATION
         * Naive method of just instantiating bitmap datas as we need them
         * Memory Used: 4603904
         */

        /* TEST_WORST_CASE_SCENARIO
         * Cloning the bitmap datas for every icon
         * Memory Used: 5672960
         */

        /* TEST_BITMAPLIBRARYMANAGER
         * Uses the bitmap library to manage bitmap data instantiation
         * Memory Usage: 3575808
         */

Yay! Memory savings. And it's easier to clean up after them and instantiate them. Source code in the Google Project.

Post Metadata

Date
October 24th, 2008

Author
urbansquall

Category


9 Comments


  1. Gambrinous

    Thanks for the code – was looking to do something very similar when I came across this. What do you think would be the best way to model game tiles using this? I’m very new to flex so I’m not very clear on the best way.

    I have a class for tiles which extends Bitmap; I then use a map (2d array) of tiles created from a map editor which at start up is init’d to be an array of GameTiles. I set the .bitmapData of each new GameTile as they are init’d for the first time (via your BitmapLibraryManager).

    Am I going about this the wrong way?



  2. Panayoti

    Nope, that sounds like a great way to do it.


  3. Hi there, really enjoying the blog. Very informatiove and well written. I tried out the BitmapLibraryManager but it threw an error in the createBitmap method when a second library class was added. I considered using describeType to query whether an image existed but in the end I’ve fixed it the quick and dirty way; by putting the if( library[ a_name ] != null ) {…} statement with a try…catch block. Keep up the good work!


  4. This is a great class I already use, one question though – why didn’t you include a method like getBitmapData() along with createBitmap()? I guess it may conflict with general architecture, but I can’t see why exactly.


  5. It’s been some time since I last reviewed this code. I believe I was discouraging access to the bitmapData because that would let client code manipulate the stored version of the bitmapData which violates part of the responsibility of the manager.


  6. Ok, got it and have to agree. I’ve got a problem using the BitmapLibraryManager class, and I’m not sure where is my fault as seems like I’m doing everything right. At start I create and register the libs:

    var BL_BG : BitmapLib_BG = new BitmapLib_BG(); BitmapLibraryManager.registerBitmapLibrary(BL_BG); var BL_UI : BitmapLib_UI = new BitmapLib_UI(); BitmapLibraryManager.registerBitmapLibrary(BL_UI);

    After that I can sucessfully call BitmapLibraryManager.createBitmap() to create bitmaps, but ONLY those that are defined in FIRST lib (BL_BG), and when I try to create bitmap that was defined in second lib – I’ve got an error during execution! I tried to swap libs – same result – only first lib get registered and its bitmaps can be used.


  7. Unfortunately, Alex, it is going to be a week at least before I can dig into the code and get it fixed. If you’re in a rush I would definitely recommend taking a shot at fixing it yourself (and posting the solution). Thanks!


  8. I’m not sure if I’ll be able to find a solution (sorry, just started to learn AS3), but I’ll try! As a temp solution – I just use only one bitmaps library for now – my current project is of compact scale, so I’m ok with it for now.


  9. Ok, guys, looks like I’ve managed to fix the bug – now I’m able to use multiple bitmap libs. Here is the fix: BitmapLibraryManager.as line 92 WAS: if(library[ a_name ] != null ) NOW: if(library.hasOwnProperty(a_name) == true )

    Please check out if it is a valid solution!


Leave a Reply