Optimisation is about making your code more efficient. Usually you’ll optimise for speed — not to make the *gameplay* faster, necessarily, but to keep the game running smoothly, with no lag.
(If your SWF is a few MB larger than you’d like, you’d want to optimise for *size*, but that’s a different topic for a different post.)
The hundreds of tricks and techniques to do this boil down to one principle:
###Don’t make Flash do more work than it needs to
For example, suppose you have a line like this:
var newX:Number = ( 47 * Math.sin( Math.PI * 23 / 109 ) / 121.88 ) + player.x;
…and you run that line every tick or every frame. Look at all the work you’re making Flash do!
It’s got to get the value of pi and multiply it by 23, then divide that by 109, then get the sine of that number, then multiply that by 47, then divide it all by 121.88, and *finally* add the player’s x-position.
If you grab your calculator, you can find that 47 * Math.sin( Math.PI * 23 / 109 ) / 121.88
is 0.237317256
. That’s not going to change; we don’t need to make Flash keep calculating that over and over again. So that line can be rewritten:
var newX:Number = 0.237317256 + player.x;
Suddenly, Flash has much less work to do — you’ve done the work for it.
Let’s look at some better examples…
###Creation is slow
Whenever you write someObject = new Whatever()
, Flash has to do a whole bunch of stuff behind the scenes involving memory and references and goodness knows what else. This takes time. Learn from eco-protesters and recycle, instead.
For example, in my avoider game I create new enemies at the top of the stage, move them down every tick, and remove them when they reach the bottom.
So, Flash has to deal with a call to new Enemy()
every few ticks — slow!
Instead of removing the enemies that reach the bottom, I could *move* them back to the top, and reuse them:
This requires more code (and more work on our part); rather than writing:
newEnemy = new Enemy( startX, startY );
…we’ll have to keep track of old enemies that have moved off the screen, then pick one when it’s needed and call:
oldEnemy.x = startX; oldEnemy.y = startY;
It’s a trade-off; working out all the new code logic requires time and work on our side, but reduces the time and work required by Flash — though we only have to write the code once!
###Drawing is slow
Any time there’s a change on the screen, remember: Flash has to redraw all those pixels. Sometimes, setting your game’s frame rate to 24fps can actually make it run more smoothly than at 30fps, because there’s a little extra time each frame to do all the drawing work.
Alpha is a source of lag. If you’ve got a semi-transparent object (object.alpha = 0.5
) then Flash has to draw that object *and* the object behind it:
Graphical filters require a lot of work on Flash’s part, too. Calculating (and then drawing) a glow, a shadow, or a blur is a heavy operation.
Do you need to apply these effects on the fly? Often you can generate them in Photoshop beforehand.
When you’ve got a lot of objects on-screen at once, it can even be faster to bypass Flash’s built-in drawing routines altogether, and write your own. (I have a tutorial on “blitting” like this lined up for next week.)
###Pixel-perfect collision detection is slow
Flash’s DisplayObject.hitTestObject() method is a simple way to detect whether the axis-aligned bounding boxes of two objects are overlapping:
…but this isn’t always good enough:
We can use a pixel-perfect collision method (such as this one), but these are very slow — you’re making Flash check every single pixel of one object against every single pixel of the other, to see if any overlap. If there are a lot of potential collisions, this can take a loooong time.
Since each method has its advantages (speed vs. accuracy), we can use a combination of the two: use hitTestObject()
to see if any two objects are overlapping, and if they are, use a pixel-perfect method to see if they’re actually colliding. It’s slower that just using hitTestObject()
, but much faster than using only the pixel-perfect method — and you get the accuracy of the latter.
###Optimise your design, too
You know what’s faster than using the two-stage collision detection routine outlined above? Not needing to use pixel-perfect collision detection at all.
If all your objects fit snugly inside rectangles, you’ll be fine just using hitTestObject
.
Likewise, if you use simple line-art, you probably won’t need alpha transparencies or fancy graphical filters. If you only have eight objects on-screen at any one time, you don’t have to worry about creating new ones.
Sometimes it’s OK to let restrictions alter your design.
###Avoid premature optimisation
Optimising code as you write it is a waste of time.
That first draft should be loose and easy to change; focus on getting it working and trying out new features before you worry about making it lightning fast.
If you try to make every line perfect as you write it, it’ll slow you down. Plus, you’ll be reluctant to change it later.
Also, don’t *over*-optimise. Consider this:
if ( player.x > playingField.rightEdge.x ) { player.x = playingField.rightEdge.x; }
It would be faster to run:
if ( player.x > 150 ) { player.x = 150; }
(…assuming that playingField.rightEdge.x is 150, of course.) But the speed gains here are minimal, and we lose flexibility; what happens if we move the playing field at some point in the game’s development? We’ll have to go back and change all those values of 150 to the new value — manually.
You don’t have to optimise every single piece of code. Concentrate on the slowest ones.
###Links
There are a lot of quirks to memorise. For instance, value = value / 5
is much slower than value = value * 0.2
. Fortunately, a number of awesome people in the community have already listed these:
– ActionScript 3 Optimization Techniques (PDF) by Joa Ebert
– Quick as a Flash by Grant Skinner (this is a presentation; click it, then press left and right to move through the slides).
– Code Optimization category of ActionScript Wiki, also run by Joa Ebert
– Tips on How To Write Efficient AS3 by Shane McCartney
– AS3 Speed Tests, a community-maintained page which itself contains links to yet more lists
If you want to run your own tests (and you should), check out Grant Skinner’s AS3 Performance Testing Harness. Lee Brimelow posted a screencast explaining how to use it here.
Got any tips, techniques or links that I’ve missed? Stick them in the comments 🙂
{ 32 comments… read them below or add one }
Nice tips RT @MichaelJW: Learn to optimise your AS3 code for speed: http://bit.ly/bulGfd
This comment was originally posted on Twitter
Learn to optimise your AS3 code for speed: http://bit.ly/bulGfd
This comment was originally posted on Twitter
Michael,
Do you know any performance analyzers for AS3 code such as Intel VTune for other programming languages? It would be very useful for optimizing flash games.
I was sure pixel perfect collision detection already first check if two objects are overlaping.
Is there any way of reducing lag that comes from glow, blue, etc without photoshop? Since we lose flexibility there too. If we want to change glow to other color later it will be much harder. Can we tell flash to convert those objects to some kind of bitmap picture and then forgot about all filters?
Great tutorial!
Great info. I was wondering if there were already lists compiled of which things are faster than others, so thanks for the links.
Regarding optimizing lines, I tend to save a commented out copy of the original line right above it, so if I change something in the way the code works, I don’t have to start from scratch and try to figure out what in the world I was thinking when I wrote and then shortened down that line.
For instance:
And
Learn to optimise your AS3 code for speed and performance: http://bit.ly/bulGfd
This comment was originally posted on Twitter
Learn to optimise your AS3 code for speed and performance: http://bit.ly/bulGfd
This comment was originally posted on Twitter
Learn to optimise your AS3 code for speed and performance: http://bit.ly/bulGfd (via @activetuts)
This comment was originally posted on Twitter
Learn to optimise your AS3 code for speed and performance: http://bit.ly/bulGfd (via @activetuts)
This comment was originally posted on Twitter
Learn to Optimise your AS3 Code for Speed — Michael James Williams: Learn to Optimise your AS3 Code for Speed
… http://bit.ly/b4kMc7
This comment was originally posted on Twitter
@kustrle – Yes, it is possible to save the “filtered” version of DisplayObjects as BitmapData and use that the entire time.
If all your enemies of a certain look the same, you can apply all the filters before the game starts, however, if each enemy is different in it’s own way, you can apply the filters once they are needed.
This is a little bit of “quasi-code” of how to add a glow filter to an enemy if it is enraged. Flash only needs to calculate the glow once, and since I’m also no longer using vector graphics, it speeds up the rendering time enormously. There are better ways, but this describes it simply.
In fact, there is an entire field of options and projects where people use BitmapData to increase speed and allow more items on the screen, as rendering too many vectors tends to be slow for the Flash Player.
Here are a few links that might point you in the right direction.
EDIT: The spam filter keeps stopping me, so I probably have too many outgoing links.
I posted this same comment (with links) on my blog, so you can reach them there:
http://iqandreas.blogspot.com/2010/02/i-originally-posted-this-as-reply-to.html
I’m in the process of developing a simple “tile game” framework that uses only drawn bitmaps, so keep an eye on my blog for future updates.
Thanks Andreas.
muito bom !! RT @MichaelJW: Learn to optimise your AS3 code for speed: http://bit.ly/bulGfd
This comment was originally posted on Twitter
I’m really happy you made this tutorial! Your tutorials are always easier understand.
The recycling idea is very fantastic, mainly for shooter games where there are thousands of enemies and bullets moving.
I usually use the TweenMax ( http://www.greensock.com/tweenmax/ ) to make the blur and glow effect, but now I’ll think about its use.
And it’s very good you alerted that optimizing the game while developing is bad.
One thing I want to talk about: I see that this game ( Mechanical Commando 2 – http://www.kongregate.com/games/BerzerkStudio/mechanical-commando-2 ) has a scrolling system and that the objects that you can’t see are hidden or deleted (you may see it better when playing in low quality). Do you know if it really help to the script speed?
I’m also interested in the post about optimizing for size (reducing MB amount). What I know about this is that the audio files are the main evil.
I wouldn’t advise people to optimise code by hard-coding literal values (commonly called magic numbers), as it leads to code that’s a lot harder to maintain.
Imagine taking over a project which contained the line of code in your example:
How am I meant to know what the literal value represents?
A better way to solve this problem would be to have each literal value in your expression (47, 23, 109, 121.88) set as constants with names that describe their purpose and abstract the calculation into it’s own method.
The optimisation that you’re trying to achieve could then be accomplished by caching the value of the calculation as a class variable and adding the player.x value within the enter frame loop or wherever it’s required.
.-= Cameron Yule´s last blog: Show redraw regions in Flash =-.
Cool, I didn’t know this stuff before.
@grdshch: I’ve never heard of VTune before. Can you explain to me what it does?
@kustrle: You’re probably right about PixelPerfectCollisionDetection checking for overlap first. But it’s a good example nonetheless 🙂
Andreas has already answered your question about glows and so on (thanks Andreas!) — I have a tutorial on blitting which you might find useful coming up soon as well.
@Andreas: Good tip about keeping the old line as a comment!
And yeah, my spam filter is a little overzealous sometimes. Sorry about that.
@SergioAwoke: Thanks 🙂 And thank you for suggesting this post. It’s difficult to say, “you must never do this or your game will be slow;” you really need to look at the whole thing at once and see what will make the most difference. Sometimes you’ll be able to skip obvious optimisations without it having too much of an effect on performance.
Hiding or deleting objects should increase the speed, yes. I’m a little hazy on the details but I think Flash draws objects that are in the display list even if they aren’t on the screen. Or maybe it just does some calculations, but not much. I’ll have to look it up…
@Cameron: I totally agree 🙂 I’d probably define a class-wide var and set its value to
( 47 * Math.sin( Math.PI * 23 / 109 ) / 121.88 )
in the constructor.@Arxanas: Cheers 🙂
@Cameron Yule –
Still, calling constants (I believe) still takes a toll on the the speed, especially in a lot of loops, however, it’s definitely a lot faster than recalculating the values each time.
So, are you saying something like this? (I just really like code, and it helps beginners)
Good idea. but check out my comment for another way to make it “easily maintainable” and understandable to other developers
http://gamedev.michaeljameswilliams.com/2010/02/10/optimise-as3-for-speed/#comment-3589
@Andreas: I think it’s swings and roundabouts here. Yours is faster, but it’s harder to change if you have such magic numbers throughout your code. If I have dozens of lines referencing
PLAYER_X_OFFSET
then I can just change the value of the definition; if those lines are referencing 0.2376..whatever, then it’s risky to hit Find And Replace in case there are two different constants in play that happen to have the same value.I suppose one way to get around this would be to do:
That way, I could find/replace
0.237634/PLAYER_X_OFFSET/
throughout my code and not worry about it affecting anything else.Er, asterisks make normal text go italic. So… well, you know what I meant.
@Michael,
VTune is a powerfull code profiler which can tell you how much time your every function takes during the program running. This means that you may detect which functions you should optimize first and which may be ignored.
E.g. if function A() took 20% of execution time and every other function took less then 1% then you need to optimize A() only and may ignore others.
I’ve just found that Flex Builder 3 and Flash Builder 4 should contain embedded profiler. Now I’m downloading Flash Builder 4 Beta 2 release to check it.
Ah, right. Yep, that sounds like the profiler 🙂 Now you’ve downloaded it, what do you think of it?
I sometimes use the profiling tool of Flash Builder 4, but I don’t get why some functions named with brackets ([ ]) (e.g [render]) are only loaded 1 time and take a long time.
Sorry, don’t know anything about that :S
Interesting read! If I can ever finish creating a game I’ll put some of these into place 🙂
.-= Bigfoot´s last blog: Update! =-.
Premature optimization – is evil. Without professional profiling, debuging and well tested library or collection of snippets this may produce unpredictable results in some cases.
@Bigfoot: Thanks!
@Indiefox: Yes, definitely. It might feel productive, but it’s just wasteful.
Very intersting reading, thank you for sharing…
Do you think copyPixels is faster than Draw?
Cheers, Lorenz.
As far as I’m aware, copyPixels() is faster, but it really depends on the situation. The best people to ask about this are Jeff and Steve Fulton of 8bitrocket.
I’m developing my first flash game and I see now how performance is really a very big issue. One thing I’ve found out is that you should try using the copypixels function instead of the draw function since it’s a lot faster. And also, you can have separate update and rendering methods so you can still update the game at 60 FPS for example but only render it a 30FPS…
Anyway, great stuff!
Thanks!!
suppose for fighting game we use a hero character with the bunch of animations together, and finally we play at particular moment….is it best method? or should we need to make all animation separately? and add or remove when when moment require . Pls tell me ….
I would add, do not work on “blind” optimizations, profile your code , by using Adobe Scout for example to discover which portion of the code needs optimizations.
http://www.guihaire.com/code
Ben.
{ 2 trackbacks }