PHOBOSLAB

Blog Home

What I Learned About Flash and ActionScript 3

I completed my first real Flash project last week. It’s an animation for a musical piece and it’s called Venetianization (long load times, be patient). One of the goals of this project was of course to learn Flash, which however I still don’t know how to use. Instead I learned ActionScript 3. So, there is not a single element on the stage; everything is scripted. And to my own surprise, I quite like ActionScript.

ActionScript 3 is the embedded scripting language of Flash 9 and a complete rewrite of its previous versions. I only had a short look into ActionScript 2 and did some simple stuff with ActionScript 1 at work aeons ago, so I can’t tell you exactly what changed. But I can tell you that ActionScript 3 is really clean and thoughtfully designed. It takes the very flexible nature of ECMAScript (Javascript) but adds lots of instruments to organize and structure your code more strictly. You are not forced to use those, but you’ll help yourself greatly if you do so.

Of course there are also some (many) things that don’t work as good as they are supposed to. Most of them, I believe, are to blame on Flash itself, rather than ActionScript.

The biggest problem I encountered is timing. You absolutely can’t rely on timers or timed events in Flash. If you set your MovieClip to 30 FPS and print out the times for each frame you’ll get pretty random results. Try it:

this.addEventListener( Event.ENTER_FRAME, 
    function(e:Event) {
        trace( (new Date()).getTime() );
    }
);

You won’t get equal intervals of 33ms (1000ms / 30 FPS) like one could expect, but something between 10ms and 90ms. You won’t even get 30 FPS.

So if you want to do anything within a certain amount of time, don’t rely FPS or intervals. Always calculate your own tick based on the time difference between the last and the current frame. So, inside your class, just do the following:

private var last:Number = (new Date()).getTime();
private var speed:Number = 10; // 10 pixels per second

function onEnterFrameCallback( e:Event ) {
    var current:Number = (new Date()).getTime();
    var tick:Number = (current - this.last)/1000; // fractions of seconds
    this.last = current;

    my_object.x += this.speed * tick;
}

Or, even simpler than that: If you want to sync your animation with your music, just ask for the current playing position of your sound file in each frame:

// “TechnoGebums” is the exported class name of your sound file in the library
private var soundtrack:TechnoGebums = null; 
private var channel:Channel = null;

function begin() {
    this.soundtrack = new TechnoGebums(); 
    this.channel = this.soundtrack.play();
}

function onEnterFrameCallback( e:Event ) {
    var current:Number = this.channel.position;
    // (…)
}

This way I was able to perfectly sync my animations with the music. No matter how many FPS I wanted, or how many FPS I really got on slow computers. I still had effects that were early or late by some 20ms. But this is barely noticeable, since everything will resync itself to the music. So even if you loop your track 200 times, your animations won’t lag behind.

I’ll try to clean up the code and upload all my source files for this project in the next few days.

Sunday, December 9th 2007
— Dominic Szablewski, @phoboslab