Back
Loading external images for use with Flixel Sprites

One of Flixel’s limitations is that it doesn’t have a native method for creating a FlxSprite with an image loaded at runtime. All of the solutions I found via Google involved either editing Flixel itself, or copy-pasting a bunch of Flixel code.

I didn’t want to do that, so I came up with a better way.

This article assumes that you already know how to actually load external images into Flash. If not, you can read up on that here.

First, let’s quickly understand why Flixel doesn’t support external images. Here’s the signature to FlxSprite’s loadGraphic function:

loadGraphic(Graphic:Class, Animated:Boolean = false, Reverse:Boolean = false, Width:uint = 0, Height:uint = 0, Unique:Boolean = false):FlxSprite

You’ll notice that the function requires a Class as its first argument. This is convenient for when you embed graphics into your game, since you get a Class when you embed a graphic with Flex:

[Embed(source="../../resources/images/sprites/hat.png")] private static var HatSprite:Class;

But when you’re loading external images, you don’t get a Class to work with — you get a DisplayObject, which you can’t pass in to loadGraphic.

The solution I came up with was to package up the DisplayObject in a Class in such a way that lets Flixel get what it needs out of it.

I took a look at what Flixel actually does with the class you give it. It turns out it does two important things — it will instantiate a copy of the class and read its bitmapData attribute, and it will cache that data based on a string unique to that particular class. Based on that, I came up with the following class:

package p_util {
  
  import flash.display.BitmapData;
  
  //
  // This class is a hack designed to allow using externally-loaded images in Flixel.
  //
  public class ExternalImage {
    
    private static var data_to_load:BitmapData;
    private static var unique_id:String;
    
    public function ExternalImage():void {}
    
    public static function setData(data:BitmapData, id:String):void {
      data_to_load = data;
      unique_id    = id;
    }
    
    public static function toString():String {
      return unique_id;
    }
    
    public function get bitmapData():BitmapData {
      return data_to_load;
    }
    
  }
  
}

Let’s first look at an example of how to use the class, and then I’ll explain how it works.

// This is the callback used by Flash's Loader class. Assume that test_sprite is a FlxSprite
// that is defined and instantiated somewhere already.
public function onLoaderComplete(e:Event):void {
  ExternalImage.setData(e.target.content.bitmapData, e.target.url);
  test_sprite.loadGraphic(ExternalImage);
}

Here we’re calling the static method setData of our ExternalImage class. We pass in the BitmapData received from the Loader, as well as the URL of the image. You can use any string at all as the second parameter — the only condition is that for each image you load, you need to use a string unique to that image (we’ll see why in a second). And what better unique string for an image than a URL to it? Lastly, we call loadGraphic on some FlxSprite, passing in ExternalImage in place of the embedded Class you would normally pass in. That’s all you need to know to get going — you now have a FlxSprite that uses an external graphic! Note that you can use this for anything in Flixel that loads an image — tileblocks and tilemaps will work too.

So how does it all work?

When you call ExternalImage’s setData function, the BitmapData and string are stored statically as data_to_load and unique_id respectively. When you pass ExternalImage into loadGraphic, Flixel will, as I mentioned before, create an instance of ExternalImage and read its bitmapData attribute. Since we have a non-static getter called bitmapData, which returns data_to_load, Flixel is able to read the bitmapData that we set, just as if we had passed in an embedded image class.

The purpose of unique_id requires a little understanding of Flixel’s internals. Flixel likes to cache the graphics you use. This is a very good thing — say you created 500 FlxSprites that all used the same graphic. If Flixel didn’t cache the graphic, you would have 500 copies of that image sitting in memory. The problem for us is the way that Flixel caches graphics. Flixel associates each graphic with a unique string. When you call loadGraphic, Flixel will check to see if the class you passed in has the same unique string as one it has used previously. If so, it will load the cached graphic instead of the one you passed in.

The string Flixel uses to identify each graphic is based on the Class you pass in. Flixel simply converts the class to a string and uses that as the graphic’s identifier. This works fine normally — say you embedded two sprites, one called PlayerSprite and one called EnemySprite. The class PlayerSprite will get converted to the string “PlayerSprite”, and EnemySprite will get converted to “EnemySprite”. Since these two strings are different, the graphics get stored separately in the cache.

Our problem is that we’re always passing in the class ExternalImage to loadGraphic, so Flixel is going to come up with the string “ExternalImage” every time, and it will always load the same cached image. That’s where our static toString function comes in. It’s very important to notice that it’s a static function. If it were not static, the function would only apply to instances of ExternalImage, and we need it to apply to the class itself. Our toString function just returns unique_id. This is why it’s important to pass in a unique string for each graphic. Flixel will cache each graphic separately, and you can use as many external images as you want.

So there you go. It’s a bit complicated in how it works, but I think it’s very easy to use. And we didn’t have to edit Flixel at all!


Comments

Hello there,

Im using your code for loading some images into a FlxSprite , but for some reason i only get half of the image. Any ideeas why?

Thanks in advance.

I actually fixed the issue (silly me, it was a problem of the position of the sprite in regard to the size of the flixel 'world').

But I do try to solve another issue which is giving me headaches for a few days: im trying to load several image using your class and your method, but the problem im having is all the sprites i create (FlxSprite) have the last loaded image. I think it has to do something with the fact that the class is static, but i havent yet found a way to work around it. Maybe you have some suggestions?

Thanks in advance.

Canada Goose CG55 Trillium Parka :

Site Map :

.The capability to plug on is optional because car also has a air engine.There are a number economic advantages of a lot of these hybrids throughout regular cars and trucks.You incorporate the use of the plug-in hybrid car regularly concerning short trips and because it is known that a gas generator only kicks in once it absolutely is required to the petrol efficiency is normally fantastic

<strong><a href="http://www.moretiffanys.com/ ">tiffany</a></strong><br><strong><a href="http://www.moretiffanys.com/ ">tiffany and co</a></strong><br><strong><a href="http://www.moretiffanys.com/ ">tiffany jewelry</a></strong><br><strong><a href="http://www.moretiffanys.com/ ">tiffany online</a></strong><br><strong><a href="http://www.moretiffanys.com/tiffany-bracelets-c-2.html ">tiffany bracelets</a></strong><strong><a href="http://www.moretiffanys.com/tiffany-earrings-c-5.html ">cheap tiffany earrings</a></strong><br><strong><a href="http://www.moretiffanys.com/tiffany-necklaces-c-6.html ">discount tiffany necklaces</a></strong><strong><a href="http://www.moretiffanys.com/tiffany-charms-c-3.html ">tiffany charms on Sale</a></strong><br><strong><a href="http://www.moretiffanys.com/tiffany-necklaces-c-6.html ">tiffany necklaces online</a></strong><br><strong><a href="http://www.moretiffanys.com/tiffany-accessories-c-1.html ">tiffany accessories</a></strong>

<strong><a href="http://www.christianlouboutindown.com/ ">Christian Louboutin Shoes</a></strong><br><strong><a href="http://www.christianlouboutindown.com/ ">Christian Louboutin On Sale</a></strong><strong><a href="http://www.christianlouboutindown.com/ ">Christian Louboutin Sandals</a></strong><br><strong><a href="http://www.christianlouboutindown.com/ ">Discount Louboutins</a></strong><strong><a href="http://www.christianlouboutindown.com/ ">Christian Louboutin Outlet</a></strong><strong><a href="http://www.christianlouboutindown.com/index.php?main_page=index&cPath=19 ">louboutin boots over the knee</a></strong><strong><a href="http://www.christianlouboutindown.com/index.php?main_page=index&cPath=19 ">over the knee christian louboutin boots</a></strong><strong><a href="http://www.christianlouboutindown.com/index.php?main_page=index&cPath=30 ">christian louboutin sneakers studded</a></strong><strong><a href="http://www.christianlouboutindown.com/index.php?main_page=index&cPath=25 ">Discount Louboutin Sandals</a></strong><strong><a href="http://www.christianlouboutindown.com/index.php?main_page=index&cPath=29 ">christian louboutin flats online sale</a></strong>

<br><strong><a href="http://www.watchesoff.com/ ">replica swiss watches</a></strong><br><strong><a href="http://www.watchesoff.com/ ">Classic swiss watches</a></strong><br><strong><a href="http://www.watchesoff.com/ ">rolex swiss watches</a></strong><br><strong><a href="http://www.watchesoff.com/ ">omega swiss watches</a></strong><br><strong><a href="http://www.watchesoff.com/ ">watches online sale</a></strong><br><strong><a href="http://www.watchesoff.com/tag-heuer-carrera-Classical-Watches-c-90_91.html ">tag heuer carrera watches</a></strong><br><strong><a href="http://www.watchesoff.com/zenith-class-Classical-Watches-c-635_637.html ">zenith class watch</a></strong><br><strong><a href="http://www.watchesoff.com/rolex-cellini-Classical-Watches-c-1_18.html ">rolex cellini watches</a></strong><br><strong><a href="http://www.watchesoff.com/bvlgari-Classical-Watches-c-326.html ">watches bvlgari</a></strong><br><strong><a href="http://www.watchesoff.com/eterna-kontiki-swiss-watches-Classical-Watches-c-373_375.html ">eterna 1935</a></strong>

<br><strong><a href="http://www.livelywedding.com/ "> evening dresses</a></strong><strong><a href="http://www.livelywedding.com/ ">wedding dresses</a></strong><strong><a href="http://www.livelywedding.com/ ">cheap wedding dresses</a></strong><strong><a href="http://www.livelywedding.com/ ">discount wedding dresses</a></strong><br><strong><a href="http://www.livelywedding.com/wedding-dresses-2010-c-1.html ">Wedding Dresses 2010</a></strong><strong><a href="http://www.livelywedding.com/wedding-dresses-2010-c-1.html "> wedding dress 2010</a></strong><br><strong><a href="http://www.livelywedding.com/mermaid-wedding-dresses-c-7.html "> Mermaid bridal Dresses</a></strong><br><strong><a href="http://www.livelywedding.com/bridesmaid-dresses-2011-c-19.html "> 2011 bridesmaids dress</a></strong><strong><a href="http://www.livelywedding.com/beach-wedding-dresses-c-3.html "> Beach Wedding gowns</a></strong><strong><a href="http://www.livelywedding.com/mermaid-wedding-dresses-c-7.html "> buy Mermaid Wedding Dresses</a></strong>

<br><strong><a href="http://www.freshreplicawatches.com/a-lange-sohne-watches-c-567.html ">A. Lange & Sohne watches</a></strong><br><strong><a href="http://www.freshreplicawatches.com/a-lange-sohne-watches-c-567.html ">Replica A. Lange & Sohne watches</a></strong><br><strong><a href="http://www.freshreplicawatches.com/a-lange-sohne-watches-c-567.html ">fake A. Lange & Sohne watches</a></strong><br><strong><a href="http://www.freshreplicawatches.com/a-lange-sohne-watches-c-567.html ">copy A. Lange & Sohne watches</a></strong><br><strong><a href="http://www.freshreplicawatches.com/a-lange-sohne-watches-c-567.html ">cheap A. Lange & Sohne watches</a></strong><br><strong><a href="http://www.freshreplicawatches.com/jaegerlecoultre-watches-c-769.html ">Replica Jaeger-LeCoultre watches</a></strong><br><strong><a href="http://www.freshreplicawatches.com/audemars-piguet-watches-c-582.html ">Audemars Piguet Watches</a></strong><br><strong><a href="http://www.freshreplicawatches.com/fp-journe-watches-c-1018.html ">F.P. Journe Watches</a></strong><br><strong><a href="http://www.freshreplicawatches.com/omega-watches-omega-railmaster-watches-c-804_809.html ">omega watches online</a></strong><br><strong><a href="http://www.freshreplicawatches.com/rado-watches-c-869.html ">cheap Rado watches</a></strong>

Thanks for the article - your solution is indeed much more concise than the other currently available ones. A question - have you tried doing spritesheet-style animation with this method? My first test, loading an external image from within a FlxSprite object, does not work, while nearly identical code using an embedded asset does.

Nevermind - A silly mistake on my part - forgot to add the additional parameters to the loadGraphic() call on the FlxSprite. Please feel free to delete these comments.

Feedback