boostworthyisryantaylor

Archive for February, 2008

AS3 Turbo: 16,000 Sprites @ 44fps

As you have probably seen by now, Moses Gunesch (creator of FuseKit and Go) released a very nice utility awhile ago by the name of TweenBencher for testing animation performance. My animation system performed decent considering it's list of capabilities and architecture, however it leaves something to be desired for those in need of extreme performance and/or small file sizes.

The project I am working on at Schematic right now is an excellent example of this need. Since there are thousands of components on screen inside a SWF which spans anywhere from 1000 to 10,000 pixels tall and thousands of lines of compressed XML data are being polled every 30 seconds, performance is a big deal. In order to successfully animate large quantities of sprites in an application as aggressive as this one, I set out to create a new variation of my animation system, which I have dubbed Turbo.

Turbo is the fastest AS3 animation system to date, rendering the 16,000 sprite test in TweenBencher at a blazing 44fps - that is 27fps faster than Go and even 3fps faster than the simple AS3 benchmark test it uses. These numbers were generated on a 2.4ghz/4gb MacBook Pro.

Benchmark results: (Boostworthy) AS3 Turbo
------------------
125 Sprites :: Start Lag: 0 seconds :: FPS: 98 :: End lag: 0
250 Sprites :: Start Lag: 0 seconds :: FPS: 99 :: End lag: 0
500 Sprites :: Start Lag: 0 seconds :: FPS: 99 :: End lag: 0
1000 Sprites :: Start Lag: 0.01 seconds :: FPS: 99 :: End lag: 0.01
2000 Sprites :: Start Lag: 0.01 seconds :: FPS: 89 :: End lag: 0.02
4000 Sprites :: Start Lag: 0.03 seconds :: FPS: 77 :: End lag: 0.08
8000 Sprites :: Start Lag: 0.08 seconds :: FPS: 60 :: End lag: 0.11
16000 Sprites :: Start Lag: 0.21 seconds :: FPS: 44 :: End lag: 0.22

PLEASE NOTE: Though I mention numbers in comparison to Go, this is not a competition by any means. I simply use Go as reference because it is the fastest system prior to Turbo. I am collaborating with Moses on Go as well.

For those currently using my animation system, the idea is to combine the best pieces of the AnimationManager and Timeline into one super fast, extensible package. Here is an example of the syntax I am using at this time:

ActionScript:
  1. // object, property name, property value, duration (milliseconds), easing equation, delay
  2. animationManager.addAnimation(new Animation(box, "width", stage.stageWidth, 2000, sineOut, 0));

Turbo is still very much a work in progress, however I would like to begin getting it into peoples hands for feedback and testing in the near future. If you are interested in learning more about Turbo or would like to participate in the feedback and testing phase, please let me know.

26 comments

AS3: Conditional Compilation Demystified

A relatively unexploited (Flex 3) feature of the mxmlc compiler is the ability to define and pass constants to your application at compile time. This is an elegant and handy way to change application behavior without having to make adjustments in your code or an external config file.

In the Flash IDE, you have the option to omit trace actions when you publish your SWF files, but this option does not exist when compiling using Flex Builder or the mxmlc compiler in general. One popular workaround for omitting traces in a non-Flash IDE project was to create custom metadata tags and wrap them around debug code in ActionScript, then run an Ant task that uses regular expressions to remove any code inside those tags right before compiling. This solution is sort of similar, but much safer and more reliable since no code is ever being copied or deleted - it's just a constant being set at compile time that you can then access inline at runtime.

Cutting to the chase, here's how it works. The command-line syntax is:

CODE:
  1. -define=YOUR_NAMESPACE::YOUR_CONSTANT_NAME,yourConstantValue

Better yet, if you are using the Flex Ant tasks:

CODE:
  1. <mxmlc ... >
  2.      <define name="YOUR_NAMESPACE::YOUR_CONSTANT_NAME" value="yourConstantValue" />
  3. </mxmlc>

Now, if you're using Flex Builder, you will want to add the definition(s) in the 'additional compiler arguments' field in the project properties dialog box. Even if you are using an Ant build file to compile, you still want to do this because it will prevent your code from being flagged with errors.

In ActionScript, you can then access this constant by simply addressing it as follows:

ActionScript:
  1. if(YOUR_NAMESPACE::YOUR_CONSTANT_NAME)
  2. {
  3.      // Do something.
  4. }

In most cases, your values will probably be booleans, though you can also pass strings, numbers, and even expressions. A few things to take note of:

    - If you pass a string in the Ant task version, you will need to wrap around it an additional set of double-quotes (and escape them) or single quotes.

    - If you pass a number or string, make sure and apply this constant to a typed constant defined in your ActionScript.

As I mentioned before, this is most useful for differentiating a debug build from a release build. I am using this approach in my logger to prevent any traces from being output unless it is a debug build. I highly recommend this practice of funneling all of your trace calls through a logger or some sort of class first so that you only need to perform the check in one location, rather than all over your application.

If this is new to you, I highly suggest taking it for a spin in one of your projects.

7 comments

AS3: Polar Gradient

I received an interesting email a few days ago asking whether or not it was possible to create a polar gradient using ActionScript. Apparently, this question stemmed back to a post on Kirupa in which the final verdict was that it could not be done. Loving sine waves and color as much as I do, I decided to spend five minutes this evening taking a stab at it myself. Here is what I came up with:

ActionScript:
  1. public function createPolarGradient(radius:Number):Shape
  2. {
  3.     var shape:Shape = new Shape();
  4.     var count:uint = 1080;
  5.     var degreesToRadians:Number = Math.PI / 180;
  6.    
  7.     for(var i:int = 0; i < count; i++)
  8.     {
  9.         var b:uint = (i / count) * 0xFF;
  10.         var g:uint = b << 8;
  11.         var r:uint = b << 16;
  12.         var color:uint = r | g | b;
  13.         var angle:Number = i / (count / 360) * degreesToRadians;
  14.        
  15.         shape.graphics.lineStyle(1, color, 1, false, LineScaleMode.NONE, CapsStyle.NONE);
  16.         shape.graphics.moveTo(0, 0);
  17.         shape.graphics.lineTo(Math.cos(angle) * radius, Math.sin(angle) * radius);
  18.     }
  19.    
  20.     return shape;
  21. }

And the end result when given a radius of '100':

AS3 Polar Gradient

You could fairly easily modify the function to accept two arbitrary colors and have the gradient fade from color parameter A to color parameter B rather than the hard-coded gray scale gradient shown above. I'll leave that one as a challenge to the reader, rather than hogging all of the fun myself. ;-)

8 comments