3 October 2011
Existing knowledge of ActionScript 3 and some familiarity with Flash Builder. (Currently Flash Professional CS5.5 does not target Flash Player 11.)
If you're new to Starling, read Thibault Imbert's article or look at some of the basic demos in the library. This article is more about how to use Starling than it is an introduction to Starling.
Additional required other products
Adobe Flash Player 11 adds a lot of great new features, but by far the coolest are the Stage3D APIs, formerly called "Molehill." Aside from just being plain neat, the new player capabilities add a performance power that is going to change how you think about making games in Flash.
If you‘ve started to explore 3D in any form, you quickly see that you are in a whole new territory. There is practically culture shock from design tools working differently than they should, all the concepts start out feeling foreign, and often coding best practices just feel counter-intuitive.
Fortunately, there is a framework called Starling that tames the 3D beast and gives you the performance benefits of 3D, while helping you build 2D games and apps. The best part is that it is built in a way that is familiar. Rather than drawing triangles, fiddling with buffers, and using the AGAL mini assembler, you get to work with MovieClips, Sprites, and TextFields that, on the surface, feel just like the ones you are already used to.
To let you see how Starling can fit into your workflow, I’ve built a game called "Whack!" using the library. You'll not only get to see how easy it is to integrate, but also see all the places where theory meets reality and how I've worked around any challenges.
Starling is a port of an iPhone Development Framework named Sparrow written by Gamua that lets developers take advantage of the hardware capabilities of coding for OpenGL, but are abstracted to Classes and APIs that are familiar to ActionScript developers.
Sparrow is the same framework but built on top of the Stage3D APIs in Flash Player 11. Strangely enough, the goal is still the same of making the development process feel more familiar to ActionScript developers. From my own use of the Flash Player 11 3D APIs, they feel like a good harmony between the normal ActionScript "feel" and the need to stay pretty true to the underlying 3D APIs. That said, Starling is not really making Flash more like Flash; it is making 3D more like 2D, and staying consistent with Flash for a bonus.
The overall framework is pretty lightweight. It does its job, and really doesn’t get in the way. I’ve found it to be very easy to extend to my specific needs as you’ll see in the game. The biggest change in my process is dealing with art. Since Starling uses very clever impostors for MovieClips rather than the real thing, you simply don’t have access to MovieClips with vector artwork, timeline animation, or frame scripts. Instead Starling (and your video card) work with bitmaps.
In the production of "Whack!," I worked with an illustrator and animator. Throughout the project my goal for the art was to not change their workflow at all, and then see what the best strategy would be for converting the assets from timeline vector assets to bitmaps and sprite sheets that are used for Starling.
I’m pleased, and more than a bit relieved, to say that it was actually pretty painless. In a few ways it has even given me thoughts on some new directions for effects that would be challenging in a normal Flash MovieClip.
When I was asked by Adobe to make a game using Starling, I wanted to make a game that put both Flash Player 11 and Starling through its paces. While any game can benefit from the hardware capabilities in Flash Player, building a Sudoku game just isn’t going to show you what the framework and the player can do.
"Whack!" is a prequel to the Whack-a-Mole arcade game (see Figure 1). The game tells the story of two friends, Jose Serrano, a California prospector, and Francis Diggington, an explorer far from his home among the mole people. Jose is helping Francis get home by giving him a helping hand, well, hammer. In exchange, Francis gives Jose any gold or other items he finds in his travels.
In case you couldn’t guess, this game is in the launch genre. I wanted to make this style of game because it has all the elements I needed to make sure the framework would work for me:
With a game concept and what feel like challenging targets, the next step was to get the art produced, and explore some different ways of prepping it for Starling.
Go ahead and play "Whack!" now.
I worked with two great artists, Chris Carman and Grant Alexander, who brought the game to life. After doing the normal planning, sketches and roughs, the final output was Adobe Photoshop documents for the backgrounds, and FLAs with graphics and MovieClips for the various animations (see Figure 2).
Have you ever seen the texture file for a 3D model where there are lots of pieces crammed into a single image file? This is pretty much how all of your artwork is going to work for Starling. The vast majority of art in the game that has to me on the screen at the same time is stored in a single PNG file.
The reason for this is that your CPU is powerful, and your GPU is powerful, but the connection through which they communicate is small and slow. By putting everything in one file, it gets sent to the GPU once and stays in memory there, eliminating a big performance issue.
There are a number of tools and DIY techniques for making sprite sheets. In this case I used Texture Packer, which has a lot of good options for customizing the sprite sheet (see Figure 3).
What takes a Sprite Sheet and turns it into a Texture Atlas is an accompanying XML file that gives each of the sprites a name and describes its location in the image. By loading the image and XML into Starling, there is a class that lets you pull each sprite individually.
When working with Sprite sheets and texture files in general, there are a few things to keep in mind.
Texture locations are identified by a system called UV coordinates, which is really just a number from 0 to 1 that says how far across from left to right to look within the image and another number from 0 to 1 for how far from top to bottom to look. You just don’t really work with pixels for textures. A side effect of this though is that there is a certain amount of fuzziness to the location, especially when scaling or rotating a texture.
If you do plan to scale or rotate, you’ll probably want to leave a couple of pixel gap between the various sprites in your texture atlas. Otherwise you might see a thin line of the next sprite over. Similarly, for elements that have to align together, it can be a good idea to plan on images that have an area for a pixel or two of overlap just to make sure you don’t see seams later on.
The last big note to keep in mind for textures is that the GPU only accepts images where both the width and height are each a power of 2 (2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, and 2048). This requirement is only for the image being sent to the GPU, not for the individual sprites in the atlas. If you use an image of another size, Flash Player will throw an ActionScript error. Flash Player will also throw an error for any images with a dimension greater than 2048, even if it is a power of 2.
For animated assets, the process actually isn’t that different. The way I settled on was to take each animated asset into its own FLA and changed the stage size to the size I wanted my images to be. I also went through and changed the behavior of any MovieClips to Graphic so that the animation could be seen on the main timeline.
In Flash Professional, I used the Export Movie feature in the File menu to export a PNG sequence for the animation, being sure to use the full document size, and giving the output images an useful name (see Figure 4). The result is a series of files with the same name but a sequential number at the end.
By importing the images into texture packer, they were put into a single file and in the XML given names based on the file names that were imported. In Starling you can request a group of textures by supplying the beginning of the assets name that all of the files have in common. With that group, you pass them to a new Starling MovieClip and you have an animated item.
When working with animated assets, be careful of nested MovieClips. They can be powerful when running as real MovieClips because of the independent timelines, but for producing an image sequence, there is a risk of having a timeline with a different number of frames so that no matter how long you ran the animation it never actually seamlessly loops. By using the Graphic symbol type, you can get a preview of the animation in higher timelines and it will export well from Flash Professional.
Once you have your textures in Starling, be aware that the pivot for all of these sprites is in the upper left corner. This will cause rotation to perhaps be different that you would expect. Fortunately, the developer can alter the pivot point through ActionScript, however the Texture Atlas system has no current way of specifying pivot information.
One small work around for this is to create your assets with extra padding on one side or another. Starling has support for a concept called a Frame (not the animated type in this case). In apps like Texture Packer, when you supply a png that has transparent space on the side, it trims it down and only stores the part of the image with content in it. However, when the XML is written, that padding is remembered in the form of a frame that is a way of saying how much padding should be put on the image.
This is important for animated elements so that each image in the sequence aligns with the others even if the edges are trimmed off. It is also useful for helping to specify the pivot point.
If you make the PNG file big enough to have the pivot point in the middle of the image and can then offset the content of the image so that it aligns using the center as its pivot, when the developer loads the texture in, they can set the pivot to half the texture’s width and height and the pivot will be in the right place. Since the excess part of the image was trimmed in packing, there is also no extra file-weight on the application.
A nice thing about textures is that they naturally repeat if you go past the edge of the texture. If you plan to use assets that tile, you do have to take some care when using texture atlases and images in general.
For images that tile in one direction, it can be in your texture atlas, but you have to plan ahead so that your tile is the same width or height as your texture. If it is a different size, instead of tiling, you would see whatever gap there to the edge of the image.
If your texture needs to tile horizontally and vertically, it will have to be in its own file. All of the game assets for "Whack!" are in one texture with the exception of the dirt tile (see Figure 5). Since it had to tile in both directions, it has to be stored separately. You also have to be sure that tiles are sized to a power of 2 in both directions. This is one of the few things that has to be forced on the designer. Almost everything else can be compensated for at development.
As a final note on designing for Starling, I’ve gotten very used to the resolution independence of vectors. When working on the assets for the game in Photoshop, we decided to start with high resolution and resize when we worked out the correct proporions for the game. Everything went smoothly with that plan, with one mindor exception. When scaling down an image keep an eye on the edge pixels. In several cases, I got slightly transparent edges that showed up when I tried to align various images together.
Developing for Starling was not significantly different from working with a normal ActionScript project. For me, the hardest part was really having to set aside Flash Professional. There are plenty of things that I like to lay out visually and then enhance through code. If you are the type of developer that moved to Flash Builder and didn’t look back, the transition should be incredibly easy.
While coding "Whack!", I kept finding myself forgetting that I wasn’t in a normal display object. There are a few differences to note. If you are like me, muscle memory will take over, but hopefully you’ll remember this section, and finding the bug will be easier.
First, be very careful with import statements. With code completion it is easy to bring in the flash package version for the display objects or for events. This has probably been my biggest accidental mistake. Once you are in Starling though, all of the display objects must be of the Starling type.
Once you are working with the Starling display objects, take a good look through the APIs. The majority of the methods and properties that I actually use are there. If at all possible, they have the same method signatures. Of course there are a few exceptions:
When working with Starling, you will quickly learn how to use the texture atlas. I really liked how the demos that come with starling deal with textures by creating an Assets Class with static methods for retrieving textures that are embedded.
It sort of acts like a singleton for your textures ensuring that each texture is only instantiated once. If the texture were embedded in the class of the display object, each instance would be uploading the same texture to the GPU with pretty disastrous results.
Also, once you start working with the textures themselves, be aware that height and width are not always reliable properties. If a texture has a frame on it, that value is not represented in the texture width. You have to check for the separate frame object on the texture object. Unfortunately, if a frame was not set for the texture in the XML, the frame property is null, so you pretty much always have to use a condition looking at both the frame.frameWidth and the width properties to decide which to use.
Animations in Starling are quite powerful, however they do take some getting used to. Setting up the actual animation is quite easy though. By using a texture atlas and having the various frames use the same name but with a number sequence at the end, you can ask for all textures that start with the name. Before Starling returns the vector of textures to you, it will do a sort on the names so that the number sequence will be in order.
Once you’ve instantiated the MovieClip with the vector though, things get pretty different. MovieClips do not play on their own. Starling has a concept of a Juggler instead. A Juggler is a manger that you register MovieClips and tweens with, and the juggler adjusts them automatically. While there is a central Juggler, the framework developers suggest creating a Juggler instance for each major game element.
However, if you do this, be aware that Jugglers don’t run on their own. You have to advance them yourself with a call from something like an enterFrame event.
Once you have your Juggler set up and your MovieClip added, the animation will run. Here’s where things get fun. You have a lot of new and useful controls available like the ability to change the frame rate per MovieClip, or even the duration of each frame. You can add, remove or adjust the frames of the movie clip as well.
The best way to learn from the "Whack!" source is to look through it. I’ve added a lot of comments, and ASdoc entries to hopefully full explain what everything is doing. Here a few classes to pay special attention to:
Starling is a great framework that provides you with access to the power of graphics hardware acceleration while keeping development straightforward. As you get comfortable using Starling, my biggest recommendation would be to read through the Starling source. I think it is a fairly gentle introduction to how the Stage3D APIs work. Given the straightforward tasks that Starling is doing compared to libraries like Away3D, it is easier to understand what is going on in Starling.
With Starling itself, keep an eye out for new extensions to the library. There is already an extension for particles, and my guess is that many of the common AS libraries are going to start integrating with Starling. Here are some additional resources for learning about the Starling framework and the new features in Flash Player 11: