I thought I’d explain how to get started with Starling and an obvious place to start would be how to animate content using Starling and the GPU (via Stage3D). Fortunately Starling abstracts the necessity for you to interact with Stage3D directly – it handles that in the background. The other benefit you get using Starling is that it implements an API that you are already familiar with as it closely follows the same API that is used when targeting the traditional Flash Display list. MovieClip, Image, Sprite, Button etc.
Diving In
So let’s look at how you start adding, and animating, content with Starling. The first thing you need to do once you’ve created an ActionScript project with Starling support (if you’re not sure how to achieve this check out this article), is create an instance of the Starling core engine.
1 2 | var _st:Starling = new Starling(AnimationExample, stage); _st.start(); |
As you can see, when creating the main Starling() instance you need to provide it with two parameters (it does takes additional parameters but we’ll skip over those for the time being). The first parameter is the root class you want to instantiate when Starling starts up, in this case it is AnimationExample. The second parameter is the location where you want to attach the root class instance. In this example we’re just going to target the main stage instance.
With that done all that is left now is to tell Starling to actually run, and you have probably already worked out how that is done. You just call the start() method on your Starling instance. With those two lines of code in place your main game class is complete (well for this demonstration at least), and it should look similar to this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | package { import flash.display.Sprite; import starling.core.Starling; import com.flashgen.examples.AnimationExample; public class Starling101 extends Sprite { public function Starling101() { var _st:Starling = new Starling(AnimationExample, stage); _st.start(); } } }
 |
Creating The Main Game Class
You may have noticed I deftly omitted anything to do with the creation of the main root class, AnimationExample, that we passed in to the Starling() constructor. That’s because I wanted to cover off a particular requirement of Starling. That requirement is that this class must inherit from Starling’s implementation of the DisplayObject class. Now just so you are clear, this isn’t the Flash DisplayObject, it’s the Starling implementation that goes by the same name. The most common implementation is to extend your class from the Starling Sprite class – which as you might gather extends the Starling DisplayObject class. So your base AnimationExample class would look something like this:
1 2 3 4 5 6 7 8 9 10 11 12 | package com.flashgen.examples { import starling.display.Sprite; public class AnimationExample extends Sprite { public function AnimationExample() { super(); } } }
 |
You now need to create a method called init(). This is where you’ll be placing the bulk of your code for this example. The reason you’re not placing it in the actual class constructor is down to the fact that we want to make sure the class has been attached to the stage before anything gets processed. To do this the only thing that needs to be added to the AnimationExample class constructor is an event listener that waits until the class has been added to the main stage.
1 2 3 4 5 6 | public function AnimationExample() { super(); addEventListener(Event.ADDED_TO_STAGE, init); }
 |
One thing to reiterate here is that the event we are listening for isn’t the flash.events.Event implementation it is the Starling implementation i.e starling.events.Event. I know I’m banging on a bit about using the Starling implementations of certain classes, but if you accidentally use the Flash implementation you will get errors.
Adding Assets
Starling differs from Flash in the way you commonly animate content in a couple of ways, but the main one is that it primarily uses texture atlases and sprite sheets* to render, and animate, visual content.
Texture huh? Sprite what!?
Texture Atlases and Sprite Sheets are fairly similar. Both revolve around a single large image that contains numerous smaller images. However they differ mainly in the scope of the content they contain.A sprite sheet traditionally only contains the graphical information for an individual sprite type – a soldier, for example – and includes all of the frames of animation it may need.
Texture Atlases on the other hand generally contain all of the graphical information required for an entire game, (or if the game is particularly large for each individual level), including the sprites, static assets etc. They also tend to utilize a text file (normally XML), or “atlas”, to indicate where each item is located within this single large image. By using the data in the text file it is easy to extract the items you need; and if done quickly enough you can animate something by swapping the current frame for the next frame in the sequence.
I’ve already created a sprite sheet and the associated XML file using an app called TexturePacker (http://www.texturepacker.com/). I’m not going to go into details on how to use this app in this article – I’ll save that for a dedicated post. The main thing to be aware of is how the two parts (the PNG sheet and the XML file) relate to each other. As I mentioned earlier, the XML file contains a reference to each item in the sheet and provides the x, y, width, and height of each sprite as you can see:
1 2 3 4 5 6 | <TextureAtlas imagePath="Bilbo-walk.png"> <SubTexture name="Bilbo0001" x="0" y="0" width="215" height="208" frameX="-33" frameY="0" frameWidth="295" frameHeight="212"/> <SubTexture name="Bilbo0002" x="215" y="0" width="215" height="208" frameX="-33" frameY="0" frameWidth="295" frameHeight="212"/> <SubTexture name="Bilbo0003" x="430" y="0" width="215" height="202" frameX="-33" frameY="-5" frameWidth="295" frameHeight="212"/> <!-- Additional entries removed for brevity --> </TextureAtlas>
 |
However, before we get ahead of ourselves let’s look at how you actually reference both of these files in your game. The first thing you need to do is embed both of these files using [Embed] metadata. One thing to make sure you don’t forget is to set the correct mime type for the XML file (mimeType=”application/octet-stream”). If you forget to include this in your XML file embedding code you’ll get an error and it won’t compile. You don’t need to set the mime type for the PNG sprite sheet though. You code will now look similar to this (obviously the path to your assets may be different)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | public class AnimationExample extends Sprite { [Embed(source="assets/spritesheets/Bilbo-walk.xml", mimeType="application/octet-stream")] private var AnimData:Class; [Embed(source="assets/spritesheets/Bilbo-walk.png")] private var AnimTexture:Class; public function AnimationExample() { super(); addEventListener(Event.ADDED_TO_STAGE, init); } protected function init(e:Event):void { } }
 |
Once you’ve embedded your sprite assets you need to actually create a reference to them. To do this you need to create an instance of both of these within the init() method. To work with the sprite sheet you need to create an instance of the Starling Texture() class and pass the data from the sprite sheet to this variable:
1 2 3 4 | protected function init(e:Event):void { var _t:Texture = Texture.fromBitmap(new AnimTexture()); }
 |
Notice that you use the static method Texture.fromBitmap() to grab the PNG file instance and assign it. The Starling Texture() class has other “from…” methods, which we’ll be exploring in later articles. Creating an instance of the XML file is pretty simple, you just need to make sure you cast the instance of the XML file as XML() – this is because we’re using the generic Class() class as the data type for both embedded files and to make sure the XML file is assigned correctly you need to cast it.
1 2 3 4 5 6 | protected function init(e:Event):void { var _t:Texture = Texture.fromBitmap(new AnimTexture()); var _d:XML = XML(new AnimData()); }
 |
Now that you have both of these variables you need to combine both parts to create something that Starling can work with behind the scenes. To do this you need to create an instance of the Starling TextureAtlas() class. This creates the relationship between both the sprite sheet and the XML data file that contains the positions of each sprite in that sheet.
1 2 3 4 5 6 7 | protected function init(e:Event):void { var _t:Texture = Texture.fromBitmap(new AnimTexture()); var _d:XML = XML(new AnimData()); var _ta:TextureAtlas = new TextureAtlas(_t, _d); }
 |
Making It Move
So far we’ve just been looking at how to set up Starling ready to render content for us. Let’s now look at how you actually get it to render to the screen, so you can actually see your sprites. As I have mentioned throughout this article, Starling has implementations of common Flash API classes and one of those is the MovieClip() class. However, its set up and usage is slightly different (as you would probably expect), compared to the Flash equivalent. When creating an instance of the Starling MovieClip() class.
1 2 3 4 5 6 7 8 9 | protected function init(e:Event):void { var _t:Texture = Texture.fromBitmap(new AnimTexture()); var _d:XML = XML(new AnimData()); var _ta:TextureAtlas = new TextureAtlas(_t, _d); var _mc:MovieClip = new MovieClip(_ta.getTextures("Bilbo"), 30); }
 |
Notice that you use your TextureAtlas() instance and call the getTextures() method to retrieve the sprites you want to associate with your MovieClip() instance. You can see that the getTextures() method takes a string that relates to the prefix used in the XML files name attribute:
1 | <SubTexture name="Bilbo0001" x="0" y="0" width="215" height="208" frameX="-33" frameY="0" frameWidth="295" frameHeight="212"/>
 |
This provides a mechanism to access elements contained within a single PNG and may relate to different parts of the games visuals. There is a second, optional, parameter you can provide on instantiation, which is the frame rate you wish the MovieClip() to render at. In this example, it is set to 30fps and this can be different to the main game frame rate. All you need to do now is add the MovieClip() instance to the Starling display list as the completed code shows, and test it out.
1 2 3 4 5 6 7 8 9 10 11 | protected function init(e:Event):void { var _t:Texture = Texture.fromBitmap(new AnimTexture()); var _d:XML = XML(new AnimData()); var _ta:TextureAtlas = new TextureAtlas(_t, _d); var _mc:MovieClip = new MovieClip(_ta.getTextures("Bilbo"), 30); addChild(_mc); }
 |
Hmm, Is This Broken?
Now if you tested this and Bilbo appeared on screen but wasn’t moving and you’re not sure why–don’t panic. You haven’t missed anything out – it is working as expected. You see, while the MovieClip() instance may have everything it needs to animate you need to use a different mechanism to update the frame it uses on each render cycle. To do this you need to use a Juggler. A juggler (as the name implies) juggles the frames of animation updating it each cycle. Don’t worry if this sounds a bit strange as it will become second nature once you’ve implemented it a few times.
The easiest way to implement a Juggler is to use the one that is part of the main Starling() instance. To access this, you just need reference the Starling() instance and add your MovieClip() instance to the Juggler associated with it.
1 2 3 4 5 6 7 8 9 10 11 12 13 | protected function init(e:Event):void { var _t:Texture = Texture.fromBitmap(new AnimTexture()); var _d:XML = XML(new AnimData()); var _ta:TextureAtlas = new TextureAtlas(_t, _d); var _mc:MovieClip = new MovieClip(_ta.getTextures("Bilbo"), 30); addChild(_mc); Starling.juggler.add(_mc); }
 |
Now if you save the file and test it Bilbo will animate as you would expect.
Summary
In this article you’ve seen how you can start using the Starling framework and how it differs (if only slightly) from animating content using the Flash API. You also saw how Starling works with sprites and textures and the common implementation workflow when working with these asset types.
Related Files
STR001-AnimatingSprites.zip