AS2 to AS3 Migration Cheat Sheet →← TextMate Shortcuts

Flash Performance Tips Part II

We were pretty stunned with the overwhelmingly positive response to the first part of this series. So stunned, we figured we should actually scrounge around and come up with some more useful tips.

In this next batch, we’re focusing on a blend of tips – we’re trying to specifically cover tips that will help you with your AS2 skills while simultaneously preparing for the transition to AS3.

UPDATE: Japanese translation is available here, again courtesy trick7.

Tweening Equations & Math Performance
There’s a lot to be said about programmatic motion. There’s tweening prototypes found all over the place (here and here, for example). Internally we use Adobe’s Tween packages. They’re simple and straightforward, and they perform pretty well without the need for anything complicated like a component.

That said, regardless of what you use to Tween you should consider the equations you run. Different ways of writing equations perform better or worse. Take this as an example – multiplying a decimal point benchmarks faster than dividing.

With that in mind, compare Adobe’s Strong versus Robert Penner’s Expo equation classes. The results are virtually the same – except Penner’s is far faster under stress. Before committing to an equation, sometimes it’s best to experiment and see if there’s a better solution out there…or a better way to write it yourself.

Kill Trace Actions
Not just for writing good, clean code but because tracing actually seems to bog down the Player. At least publish with trace actions Omitted. If you’re not using it already, look into the Out class. (link).

Basically the Out class has several different arbitrary “levels” of tracing: Warning, Info, Debug, Status and Fatal. It allows a developer to be more organized with their debug messaging.

We use Out for everything. As a project is winding down, we try to disable everything except the debug layer, so we can zero in on bugs for quick and easy squashing.

Optimize Bitmaps & Sound individually in the Library
It sounds painstaking (and sometimes it is), but by controlling the assets individually in your library you have much more control on the file size come compile time.

For sounds, we use AIF files and then convert them to MP3 on export. Better to start with a better quality sound and compress down than try to go up, right?

Oh, this is a good time to point out a bug with the OSX version of the IDE that continually frustrates me: Exporting sounds on 64kbps will occasionally create an awful screeching noise. It seems to be totally random, and platform specific. We just avoid 64kbps nowadays [whenever our sound designers let us].

We really like Fuel’s Library Items panel (download here). It allows for simple batch optimizing of library items…though there is a typo in the sound tab which will force you to dig around for the JSFL and string replace “kpbs” with “kbps.”

Complex Vectors and Text
You’re forcing Flash to redraw complex vectors every frame. Same with text. With dynamic text fields, put ‘em in a movieclip and set them to cacheAsBitmap. If you ever need to animate them you can unset the cacheAsBitmap, but if they’re just standing in place there’s no reason they should tax the processor.

Don’t Break Apart JPGs
The ultimate no-no. The player has to look at the JPG every frame and figure out what to draw. This is such a waste. It’s even worse if you pull a complex shape out of the JPG…now you’re forcing Flash to do double work. If you need just a portion of a JPG, use a mask…or better yet, bring it back to Photoshop and crop the piece you need.

No Looping in onEnterFrame
Running a for loop every frame is actually slower than directly defining what you need. If you have a small amount of data you need to increment, consider hard coding it.

// slow
var a = [0,1,2];
mySlow.onEnterFrame = function():Void
{
for(var i=0;i<a.length;i++) { a[i]++; }
};


// fast
var a = [0,1,2];
myFast.onEnterFrame = function():Void
{
a[0]++;
a[1]++;
a[2]++;
}

…in fact, we can take this a step further.

Avoid All Excess Looping
Let’s pretend you have a complex set of data. Storing them in as arrays sounds like the easiest battle plan, right? Wrong. It can lead to trouble. Consider this very basic example:

var error_array = [];
error_array[0] = [404,"File Not Found"];
error_array[1] = [500,"Misconfiguration"];
error_array[2] = [403,"Forbidden"];
error_array[3] = [200,"Okay"];


// assumes an outside event has fired that calls this function
onNewError($error_code:Number):Void
{
for(var i=0;i<error_array.length;i++)
{
if(error_array[i][0] == $error_code)
{
trace("Error Found!: " + i);
break;
}
}
};


function doesErrorExist($error_code:Number):Boolean
{
for(var i=0;i<error_array.length;i++)
{
if(error_array[i][0] == $error_code) return true;
}
return false;
};

In this case, its just a few items…but every time onNewError or doesErrorExist is fired, we have to loop through our entire array to find the corresponding error (if at all). There’s a better, more organized way to do this same task:

var error_obj = {};
error_obj["e_404"] = "File Not Found";
error_obj["e_500"] = "Misconfiguration";
error_obj["e_403"] = "Forbidden";
error_obj["e_200"] = "Okay";


onNewError($error_code:Number):Void
{
trace("Error Found!: " error_obj["e_" + $error_code.toString()]);
};


function doesErrorExist($code:Number):Boolean
{
return error_obj["e_" + $error_code.toString()] != null;
}

By using an object to create an index, we’re able to bypass any looping. There are times when using arrays of objects (objects populated with arrays) can be useful, too. The idea is to avoid any looping.

Avoid Non-Frame Specific Events
onMouseMove, Stage.onResize are prime examples of functions you should try to avoid doing any sort of extensive programming in. Since they fire independent of the frame rate, its plausible your user gets 5 or 10 or more Mouse Move events before the frame updates once. We find an onEnterFrame detecting mouse position works far faster.

Don’t Play Clips Backwards
Sure, it sounds like a great idea in theory, but there are serious negatives.

For starters, you need to be aware of any potential scripting on your timeline as you go backwards. You’ll need to know whether you need to ignore these events or not, which means before you know it you’ll be rewriting the Timeline entirely in ActionScript.

Second, you’re making the Player do double work. It already has to look to see what to refresh x number of frames per second…now you’re making it run code to move a timeline backwards every frame on top of that.

If your timeline is complex and you’re trying to play it backwards, you’re going to run into bugs. And if it’s simple, you should probably take the 30 seconds to keyframe it out the opposite way and just gotoAndPlay a different label. The Player (and your end users) will love you for it.

Filters are nicest on multiples o’ 2
When using a Blur Filer, use multiples of 2. The player seems to like this better. We haven’t done any specific benchmarks on this…but it seems like it can’t hurt to be safe. :)

Kill! Destroy! Dispose! Whatever.
This one is especially pertinent for AS3, given that garbage collection is far stricter than in previous versions of Flash, but it’s a good practice just the same. In every class we write, we include the following function:


function kill():Void {};

kill will wipe out any onEnterFrames, clear any intervals, remove references to movieclips, reset or null all variables, remove any references to objects, and on and on. The idea is that the only way to insure garbage collection is to make sure we’ve cleaned up our mess in the first place. We’ll know for sure that we’re not storing duplicate classes in memory. Flash will be oh so happy.

Check out Grant Skinner’s AS3 Resource Management series for more information on garbage collection, and his awesome Janitor class to help expedite your transition.

Advanced Collision Detection
hitTest is an acceptable way of detecting small collisions between instances, but there are alternatives out there that are custom built to perform much better. Here are two links to some advanced detection algorithm’s we’ve looked into before. With Recursive Dimension Clustering, the screen is divided into regions and then detection is done based on what elements fall into what regions. It’s pretty nifty and fast, and you can wow all of the babes with your newfound math babble. Another method is Grant Skinner’s Shape Based Hit Detection, which uses BitmapData brilliantly to draw a comparison of two objects and return the bounds where they intersect (if at all).

You can pull off a custom collision detection with hitTest simply by placing empty movieclips around a complex shape and hitTesting those instead of the shape itself. Better for the player to do several hitTests on simple objects than one hitTest on a complex one.

February 28th, 2007  by Stephen  /  28 Comments

Comments on “Flash Performance Tips Part II”

  1. Kick ass… that library extension is great… and I always thought to optimize in photoshop or audio app first instead of using flash to do it.

    Gianni D on February 28th, 2007 at 7:21 pm
  2. You guys are amazing. I can’t tell you how much I appreciate people sharing what they’ve learned through Flash’s school of hard knocks :)

    Nate Chatellier on February 28th, 2007 at 7:37 pm
  3. Using multiples of 2 in regards to filters increases performance by 40% according to Thibault Imbert.

    Kevin Sweeney on February 28th, 2007 at 8:48 pm
  4. I was a fan of the first article regarding Flash Performance Tips, but this one just blows it out of the water. Lots of good stuff here and I’ll probably end up reading it again a few times. Thanks for the resources and the time spent helping people like me out. Oh, and nice work on that Grindhouse web site, bigspaceship dudes, it looks pretty sweet.

    Mike on March 1st, 2007 at 12:16 am
  5. Just one more thing I forgot before. The flash “Out” class link doesn’t seem to be working. Anyone have that? I’d like to use it, as suggested.

    Mike on March 1st, 2007 at 12:23 am
  6. i find the name ‘kill()’ to be overly aggressive, i tend to use the passive - ‘cleanup()’. ;-)

    thanks for the great tips - no more looping for me!

    Kyle on March 1st, 2007 at 2:51 am
  7. Oh spaceship of greatness… could I gain access to the Out Class? It seams to be a great thing to expedite my workflow. Great work!!

    Diogo Costa on March 1st, 2007 at 6:07 am
  8. Thanks for posting part 2. I’ve been anxiously waiting for the sequel :). I love the idea of the Out class. Hopefully I’ll have a chance to check it out.

    Though I have to say that I really liked your tricks for getting around doing for loops. I’ve found troubles with trying not to do for loops on onEnterFrames and other type of events. So this will be another great tip that I’ll be looking to try.

    Rich on March 1st, 2007 at 10:34 am
  9. Yeah I’m also interested in the Out class. A link would be so fantastic.

    Joe on March 1st, 2007 at 11:47 am
  10. Oh. Why did I think Out was part of mx.utils? Silly me. I’ll post our com.bigspaceship version up ASAP.

    Jamie on March 1st, 2007 at 12:16 pm
  11. Excellent suggestions, though if they happened to be criminal offenses I’d be in jail for a long, long time. Oh, if you happen to see a certain penguin-obsessed fellow in your ranks with the initials SK, give him SUCH A PINCH! :D

    20 Ton Squirrel on March 1st, 2007 at 3:56 pm
  12. About the “Fuel’s Library Items”…You save my life! I LOVE YOU.
    For the last 2.5 years, EVERY single day i linkage 30-40 sounds in flash library manually.T-H-A-N-K Y-O-U and fuelindustries.

    Savvas Malamas on March 2nd, 2007 at 10:50 am
  13. I just keep reading..This is unbelievable.In a few lines you gave us…EVERYTHING?Oh my God..Guys make a book!Please!

    Savvas Malamas on March 2nd, 2007 at 11:09 am
  14. aye!!! great, just purely awesome great ;-)

    you guys should write a book!!!

    Lorenz on March 2nd, 2007 at 12:48 pm
  15. […] If you have not been to the Big Spaceship Blog yet, you should. They have all sorts of great tips and thoughts ripe for the taking. Their most recent article is the second post in a series of Flash performance tips. I was aware of a few, but others were completely new to me. Performance optimization may seem like a nerdy thing to some, but the process allow things to be done in Flash that otherwise would be too costly to the average processor or be a memory hog. […]

    Daily Delicious - Flash Performance and Memory Usage Tips » SOME RANDOM DUDE on March 2nd, 2007 at 5:07 pm
  16. Very helpful tips again!

    Using objects instead of array for complex data to avoid loop is cunning :)

    I’ve learned most of them in this article. You are great guys!

    Özgür ALTAY on March 4th, 2007 at 11:26 am
  17. Hey Jamie thanks for the catch on the typo in the panel. I’ve fixed it and uploaded it.

    Julian Dolce on March 4th, 2007 at 11:44 am
  18. @Julian Dolce: Thanks! Your extension has been a lifesaver here.

    For everyone else, just wanted to let you know that we’ll be posting the Out class as soon as we can. Sorry for the delay.

    I also realized that I promised an example of using a BitmapData screenshot of a section in Part 1…we’ll get that up, too.

    Jamie on March 4th, 2007 at 2:07 pm
  19. Awesome. I’m really looking forward to both of those things!

    Mike on March 4th, 2007 at 7:16 pm
  20. Out class link soon?

    Phil on March 5th, 2007 at 3:27 pm
  21. On the topic of faster filters on even numbers, the documentation says this:

    “The amount of horizontal blur. Valid values are from 0 to 255 (floating point). The default value is 4. Values that are a power of 2 (such as 2, 4, 8, 16 and 32) are optimized to render more quickly than other values.”

    So it appears values that are a power of 2 are faster, not all even values.

    zeh on March 6th, 2007 at 2:51 pm
  22. […] Flash Performance Tips Part II […]

    Hangun’s World - Blog » Blog Archive » Flash Performance Tips Part II on March 6th, 2007 at 9:27 pm
  23. Hi, I’m creating an game and was wondering if the collision detection mentioned in the tutorial is faster and better then writing a custom script which, instead of checking that you have hit an object do this : check whether in the next frame/interval you will hit the object (by checking the position/speed etc) and taking the appropiate action. Which collision solution is better/faster? Is there a collision detection blog?

    Vypa on March 19th, 2007 at 2:01 pm
  24. What software do you use to compress flv’s? I’m looking at purchasing On2’s Flix Pro from what I’ve read it looks pretty good but I wanted to get your insight.

    Thanks!

    jonathan on March 21st, 2007 at 9:40 pm
  25. […] There are a lot of great flash performance tips in this article at the Big Spaceship Labs blog. Well worth a gander.—– […]

    Flash Performance Tips at smallTransport on July 5th, 2007 at 3:54 pm
Next →