SpriteSheet Animation in AS3

Over the last few years sprite-sheet animation gained popularity among game developers. It offers some real advantages over movie clips – lighter and potentially faster performance, with the added bonus of code portability. If you plan to deploy your game on Android and iOS  as well, this is definitely the way to go.

I found that most of the tutorials on sprite sheets are for the Cocos2D engine (in Objective-C for iOS). Here I will show a practical and convenient way to animate sprite sheets in AS3, making the game perform well on both Flash in browser and AIR mobile.

UPDATE:

If you are using Starling (like I do), you might be interested in the Starling port of AnimSprite. see my post AnimSprite for Starling: a better MovieClip alternative.

There are a few off the shelf engines that use variations of spritesheets, among them Starling (Flash 11 only) and Flixel. These may be perfect for certain type of projects, but I decided to write my own classes to minimize the dependency on 3rd party code.

Demo

Click image to see the demo

Download the full demo code from BitBucket here.

The Tools

You would need a code IDE (FlashDevelop, FDT or Flash Builder) and an image tool that can pack textures. I use the popular TexturePacker, in my opinion the best texture tool for developers. If anyone knows anything better, please comment.

Preparing the assets

The animated sprite is created by the artist  with their animation package of choice. This is a sequence of images that form the animation frames.  In this case (and most others) all frames are the same size.

Open TexturePacker and import the individual images into the projects. Select json as the data format, check ‘Allow free sizes’ and make sure ‘Allow rotation’ is not checked. Publish the texture to the output folder. The setting I use can be seen here.

There are many different options with TexturePacker, that are out of scope of this article. For more in depth look, check out Chris Fletcher’s tutorial here.

Once published, you end up with a large PNG file – the texture sheet, and a json file to go with it.

Reading the texure with the AnimTextureSheet class

I created the AnimTextureSheet class to encapsulate a texture sheet and its data. After loading your animation assets, you get a BitmapData from the sheet PNG and a string from the json file. After decoding the json string, the function populateFrameArray serialize the frame data into an array which is then passed into the  newly created AnimTextureSheet.

	var seqRaw:Object = JSON.decode( sheetData );
	var animData:Array= [];
	populateFrameArray(animData, seqRaw.frames);
 
	// Sort
	animData.sortOn("id");
 
	// Create and initialize the tile sheet
	var tileSheet:AnimTextureSheet= new AnimTextureSheet();
	tileSheet.init(texture, animData);

Once initialized, the tille sheet is ready to go, and the  drawFrame() method can be called to blit a frame into a destination bitmap buffer.

UPDATE
When compiling with Flash Player 11 (or Flex 4.6) there is a build error due to the new native JSON parser:
Can not resolve a multiname reference unambiguously. JSON [..]
To resolve the problem, simply change the first line to read:
var seqRaw:Object =  com.adobe.serialization.json.JSON.decode( sheetData );

Play it

To actually display the animation,  we need a display object to hold the bitmap. For that purpose I created the AnimSprite class, that is based on flash.display.Bitmap. This class in only for convenience – you can create your own – it demonstrates the possible use cases for an animated sprite.

	private function createAnim():AnimSprite
	{
		var anim:AnimSprite = new AnimSprite();
 
		anim.initialize(_texSheet);
		anim.addSequence("all", arFrames, 16);
 
		anim.play("all");
		return anim;
	}
 
	// Call on enter frame event
	protected function onFrameUpdate(event:Event):void
	{
		if (pause){
			return;
		}
		for (var i:int = 0; i < arSprites.length; i++) 	{
			AnimSprite(arSprites[i]).updateAnimation();
		}
 
	}

The above code shows how AnimSprite is actually used.

  1. instantiate the AnimSprite
  2. initialize it with  a tile sheet
  3. add one or more sequences (indexed frames) with an individual frame rate
  4. add it to the stage.

To play it:

  1. Call play() to start playing a sequence
  2. call updateAnimation() on every frame

How it works

AnimSprite uses partial blitting technique to animate. It uses the bitmapData as a frame buffer that holds the frame image that gets displayed. On every update, the updateAnimation()  function checks if the animation frame need to advance, and if so calls advanceFrame() – that sets the dirty flag when the current frame index is changed.  The the following method is then used to draw the frame:

	protected function drawFrameInternal():void
	{
		dirty = false;
 
		bitmapData.fillRect(bitmapData.rect, 0);
		mAnimSheet.drawFrame(curIndex, bitmapData);
	}

Check out the code for more details on the AnimSprite class.

That’s pretty much it. Let me know if you find any bugs or problems.

See Also: Sprite Sheet Animation Viewer

5 thoughts on “SpriteSheet Animation in AS3

  1. This is a public repository. Without going into legal jargon, it is free for use in any project, commercial or otherwise.

  2. Thanks! I am sure this will help a lot of people. I am sure it will help me. Saved a lot of time on my project 🙂

  3. Thanks a lot, I’ve found this very useful 🙂

    Found a bug in the TileSheetHelper.as… I noticed that with some json files my tile sequences wouldn’t be in the correct order. Assigning the item.id to keyName instead of nameId seemed to solve it.

    Phew that was a pain to track down

Comments are closed.