ActionScript 3 QuickTip #1 – The Timer Class

In previous version of ActionScript there were a couple of different ways to trigger events based on time. The setInterval() and setTimeout() functions were the two most commonly used ways of calling a function after a specified amount of time had lapsed. In ActionScript 3 we now have the Timer class which lives in the flash.utils package. This class contains all the functionality that you will ever need for time-based applications. In order to use the class, you first must import the flash.utils package as seen is the example below. The Timer constructor expects one argument that represents the desired delay in milliseconds between function calls. An optional seconds argument determines the number of times to call the function. The default for this value is 0, which means that it will call the function indefinitely. If you wanted to replicate the functionality of the deprecated setTimeout() function, you can simply pass 1 as the value for this parameter.

In my example below I am creating a Timer that will fire twice a second, but I haven’t yet told it what function to call every time the delay has passed. To do this we need to respond to the timer event of the Timer class and give it the name of the function that will handle the event. At this point our Timer will be setup for use but we still need to call the Timer.start() method in order to get things started. In my implementation below I am simply doing a trace() to the output window every time the Timer fires showing how many times it has fired. To get this value I am reading the Timer.currentCount property.

[as]// We need to import the utils package
import flash.utils.*;

// Create a new Timer object with a delay of 500 ms
var myTimer:Timer = new Timer(500);
myTimer.addEventListener(“timer”, timedFunction);

// Start the timer
myTimer.start();

// Function will be called every 500 milliseconds
function timedFunction(eventArgs:TimerEvent)
{
trace(“Timer fired ” + myTimer.currentCount + ” times.”);
}[/as]

Check out the AS 3 docs to see all of the available properties and methods of this great new class.

Lee :-)


Commentary

  1. xeonarno says:

    Hi lee,

    I love you !! I love AS3.0

    Bye,
    Xeonarno

  2. Steve Nelson says:

    Must be something about Timers in the air. Keith Peters has recently posted on Timer too, with some good info about what you can expect from Timers regarding accuracy:
    http://www.bit-101.com/blog/?p=910

  3. Al says:

    where might one find the flash.utils package? The link I get lists the documentation, but I seem incapable of finding the said package.

  4. KJ says:

    Its called mx.utils now.

  5. I agree that, in the current Actionscript 3.0 implementation, timers must be used judiciously and perhaps sparingly.

    In my test, each of four timers controls one of four text letters already on the stage. The handler for each letter tweens four things: that letter’s x, y, width and height, and uses easing for each of those properties.

    The accuracy of the rendered results appears to be CPU and task-load dependent.

    When viewed as part of a (static) HTML page in a web browser, the timed tweens fail quite frequently. E.g., the finishing x, y, width or height fail in various ways — the letters don’t finish at the right screen position or of the correct dimensions. Viewed as a standalone in Flash Player, the .swf may play more smoothly and the tweens might be executed more correctly there, but it is not reliable in any sense.

    It appears as though the computational time for the tweens causes the next timer’s handler to try and “catch up” by skipping an indefinite number of intermediate steps.

    Keith Peters’s article, cited on this page, makes some good points. My next experiments will be to try approaches based on:

    * (a) the system clock, when the need is for time-accurate results — although timing when that clock gets polled could introduce some inaccuracy (poll on every enterFrame and thus create more run-time overhead? feedback welcome…)

    * (b) enterFrame or (c) testing for a condition (e.g., an object crosses a boundary or acquires a certain attribute value), when the need is to satisfy user perception of smooth, accurate animation

    * if appropriate to the context, (d) trigger on completion of something else (e.g., presumably often the best practice when loading external data/media or when working with a relatively rich and active stage)

  6. matthew says:

    It doesnt pause. Say you have an interval of 8000 ms and you pause it at 4000 (which you cant do because you must do timer.stop()) whe you start it again, it starts at 0.

    MaTT

  7. Nick says:

    Timer inaccuracy!!!!

    I’m using the Timer class at small intervals for sequencing in a drum machine application and I too am finding the inaccurate results.

    At intervals such as 50-300ms the inaccuracy is audible when triggering successive sounds. Enough to render the Timer class completely inept at sound sequencing intervals.

    I am struggling to find a way to accurately represent timings as low as 50ms in Flash, if anyone has ANY information please do let me know. I’ll be investigating using the date/time and time elapsed, but something in my gut tells me that is also trouble.

    Moreover, I have seen several flash applications that DO accurately time these events, so it’s not impossible.

    I’ve posted to numerous forums with no response.

    Any help appreciated, will check back.

  8. jason says:

    Unless things have changed with how flash works, everything is still based on frame rate. Flash goes to the frame, executes the actionsctipt and draws the assets, then displays the frame. If your flash file only runs at 12 frames a second but you want an event to fire 100 times a second, this isn’t going to happen. Nick, you could try setting your frame rate to match your beat but a lot of that depends on processing power too since flash can only process as fast as the computer lets it. I built an audio mixer a while ago but it was with pre built audio clips and I had to sync them everytime a new sound was added or removed.

  9. Dan says:

    I second the question from Nick (posted December 8th, 2007). Nick, did you happen to find a solution?

  10. huy says:

    This is very helpful for my project. Just wanna say thank you.

  11. dragos says:

    i have a pretty interesting issue with Timer in as3; i’ve made a banner and the smooth transitions that i had to do were made using some timers (thus having less timeline frames).

    My problem is that when the movie plays again(from frame 1 to ~) my timers won’t work no more!

    If u have this kind of issued pls email me!

    Regards

  12. John Sparrow says:

    @ dragos:

    Not sure if I understand your problem exactly, but does adding

    myTimer.stop();

    to the beginning of the timedFunction function help?

    J

  13. John Sparrow says:

    Dear Lee Brimelow

    Thanks for a really useful introduction to my first dabblings with AS3… this is really helpful for a project I’m planning.

    J

  14. Janne says:

    Why are different browsers returning different times?

    This is a script that fades in a movie clip:

    var startfader:Timer = new Timer(8, 100);
    startfader.start();
    startfader.addEventListener(TimerEvent.TIMER, startfadein);

    var startopacity:Number =0;

    function startfadein(event:TimerEvent):void {
    if(startopacity<100){
    startopacity++;
    }
    myMC.alpha = startopacity/100;
    }
    }

    …and the result: IE about 3 seconds, FF about 0,8 seconds. Frame rate is set to 100. What’s the problem?

  15. Futurefabric says:

    I’m currently building a visual clock in AS3 and have come up against the inaccuracy of the built in Timer class – it’s just not reliable enough.

    Done quite a bit of research and trick7′s TeraClock class seems a reliable workaround:

    http://www.libspark.org/wiki/trick7/TeraClock

  16. Triggs says:

    Hey extremely helpful flash people:

    I’m new to flash, and am trying to make a timer using this code:

    var min:Number=0;
    var hour:Number=0;

    var timer:Timer = new Timer(1000, 15);
    timer.addEventListener(TimerEvent.TIMER, onTimer);
    timer.start();

    if(timer == 10)
    {
    min+1;
    seconds=0;
    trace(\minutes:\ + min);
    }

    if(min==60)
    {
    hour+1;
    min =0;
    trace(\hour:\ + hour);
    }

    public function onTimer(e:TimerEvent):void
    {
    trace(\Times Fired: \ + e.currentTarget.currentCount);
    }
    }

    *****end****
    APPARENTLY you can’t use var timer in this way (in the if statement), I keep getting this error:

    1176: Comparison between a value with static type flash.utils:Timer and a possibly unrelated type int.

  17. sarfaraz says:

    good example

  18. sarfaraz says:

    hi im new i m making a clock but its time and current timimg comes different

    this.addEventListener(Event.ENTER_FRAME, on_enter_frame);
    function on_enter_frame(e:Event):void
    {
    var time = new Date();
    var s:Number = time.getSeconds();
    var m = time.getMinutes();
    var h = time.getHours();
    second.rotation=s*6;
    minute.rotation = m*6;
    hour.rotation = h*15;
    }

    please help me

  19. Hello there,

    Here is a timer with pause() method :)

    enjoy

    http://blog.ramonfritsch.com/t/timer-com-pause/

  20. CC says:

    Please note that Timer can drain your CPU
    See comment
    “Note that if you create a Timer *without* an execution limit (e.g. timer = new Timer(1000) ), the object will never get garbage collected until you call timer.stop(), even if you call removeEventListener(). Create a lot of them, and your CPU will get drained.

    on
    http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/utils/Timer.html

  21. orilia says:

    thank you very much! this is so useful :)

  22. Chris says:

    Dragos, the magic word you’re looking for is myTimer.reset();

    Here’s an example from my flash movie:
    **********************************************

    var tickCount = 0;
    var goTime = 9;

    var myTimer:Timer = new Timer(1000,9);
    myTimer.addEventListener(TimerEvent.TIMER, timerListener);

    function timerListener (e:TimerEvent):void{
    tickCount++;
    if(myTimer.currentCount==goTime){
    tickCount = 0;
    trace (\time’s up!\)
    myTimer.reset();
    play();
    }
    trace(\tickCount: \+tickCount);
    }
    **********************************************

    (tickCount is an extra variable I made up before I found out about myTimer.currentCount- another thing I found built into the Timer class and not explained in many of the places online that purport to explain it. I decided to use goTime as a separate variable for better maintainability.)

    This is where I finally found good documentation:
    http://www.foundation-flash.com/tutorials/timer/

    And finally, I’m amused that the anti-spam confirmation words for me ar \urethra Me.\

  23. Hi there, friend, im a little out off topic, but i´m struggling in a as2 with the setTimeout function, my problem is this if you can give me a little help. Im using setTimeout in a bunch of mc to show in specific time as the sound play´s, the problem is if I forward one frame, it all goes out of sync, it continues where stop and start´s again and all turns into a great mess. My script above, and just for remember using on two frames, im gonna post the two frames action, I than you in advance…

    First Frame
    ———————————————————————-
    import mx.transitions.*;
    import mx.transitions.easing.*;

    stop();

    my_sound_2.loadSound(“audio/qualificacao das carencias.mp3″, true);

    my_sound.stop();

    next_mc.onPress = function()
    {
    nextFrame();
    };

    prev_mc.onPress = function()
    {
    prevFrame();
    }

    TransitionManager.start(next_mc, {type:Fade, direction:Transition.OUT, duration:1, easing:Strong.easeIn});
    TransitionManager.start(prev_mc, {type:Fade, direction:Transition.OUT, duration:1, easing:Strong.easeIn});

    comprador_0._visible=false;
    comprador_1._visible=false;
    comprador_2._visible=false;
    comprador_3._visible=false;
    comprador_4._visible=false;
    comprador_5._visible=false;
    comprador_6._visible=false;
    comprador_7._visible=false;
    comprador_8._visible=false;
    comprador_9._visible=false;
    comprador_10._visible=false;
    comprador_11._visible=false;
    comprador_12._visible=false;
    comprador_13._visible=false;
    comprador_14._visible=false;
    comprador_15._visible=false;
    comprador_16._visible=false;
    comprador_17._visible=false;
    comprador_18._visible=false;

    function pausacomprador()
    {
    TransitionManager.start(comprador_0, {type:Fade, direction:Transition.IN, duration:1, easing:Strong.easeIn});
    comprador_0.line_1.gotoAndPlay(1);
    }
    function pausacomprador2()
    {
    TransitionManager.start(comprador_1, {type:Fade, direction:Transition.IN, duration:1, easing:Strong.easeIn});
    }
    function pausacomprador3()
    {
    TransitionManager.start(comprador_2, {type:Fade, direction:Transition.IN, duration:1, easing:Strong.easeIn});
    }
    function pausacomprador4()
    {
    TransitionManager.start(comprador_3, {type:Fade, direction:Transition.IN, duration:1, easing:Strong.easeIn});
    }
    function pausacomprador5()
    {
    TransitionManager.start(comprador_4, {type:Fade, direction:Transition.IN, duration:1, easing:Strong.easeIn});
    }
    function pausacomprador6()
    {
    TransitionManager.start(comprador_5, {type:Fade, direction:Transition.IN, duration:1, easing:Strong.easeIn});
    }
    function pausacomprador7()
    {
    TransitionManager.start(comprador_6, {type:Fade, direction:Transition.IN, duration:1, easing:Strong.easeIn});
    }
    function pausacomprador8()
    {
    TransitionManager.start(comprador_7, {type:Fade, direction:Transition.IN, duration:1, easing:Strong.easeIn});
    }
    function pausacomprador9()
    {
    TransitionManager.start(comprador_8, {type:Fade, direction:Transition.IN, duration:1, easing:Strong.easeIn});
    }
    function pausacomprador10()
    {
    TransitionManager.start(comprador_9, {type:Fade, direction:Transition.IN, duration:1, easing:Strong.easeIn});
    }
    function pausacomprador11()
    {
    TransitionManager.start(comprador_10, {type:Fade, direction:Transition.IN, duration:1, easing:Strong.easeIn});
    }
    function pausacomprador12()
    {
    TransitionManager.start(comprador_11, {type:Fade, direction:Transition.IN, duration:1, easing:Strong.easeIn});
    }
    function pausacomprador13()
    {
    TransitionManager.start(comprador_12, {type:Fade, direction:Transition.IN, duration:1, easing:Strong.easeIn});
    }
    function pausacomprador14()
    {
    TransitionManager.start(comprador_13, {type:Fade, direction:Transition.IN, duration:1, easing:Strong.easeIn});
    }
    function pausacomprador15()
    {
    TransitionManager.start(comprador_14, {type:Fade, direction:Transition.IN, duration:1, easing:Strong.easeIn});
    }
    function pausacomprador16()
    {
    TransitionManager.start(comprador_15, {type:Fade, direction:Transition.IN, duration:1, easing:Strong.easeIn});
    }
    function pausacomprador17()
    {
    TransitionManager.start(comprador_16, {type:Fade, direction:Transition.IN, duration:1, easing:Strong.easeIn});
    }
    function pausacomprador18()
    {
    TransitionManager.start(comprador_17, {type:Fade, direction:Transition.IN, duration:1, easing:Strong.easeIn});
    }
    function pausacomprador19()
    {
    TransitionManager.start(comprador_18, {type:Fade, direction:Transition.IN, duration:1, easing:Strong.easeIn});
    TransitionManager.start(next_mc,{type:Fade, direction:Transition.IN, duration:1, easing:Strong.easeIn});
    TransitionManager.start(prev_mc,{type:Fade, direction:Transition.IN, duration:1, easing:Strong.easeIn});
    }

    setTimeout(pausacomprador, 2000);
    setTimeout(pausacomprador2, 4500);
    setTimeout(pausacomprador3, 10000);
    setTimeout(pausacomprador4, 12000);
    setTimeout(pausacomprador5, 15000);
    setTimeout(pausacomprador6, 17000);
    setTimeout(pausacomprador7, 20000);
    setTimeout(pausacomprador8, 22000);
    setTimeout(pausacomprador9, 26000);
    setTimeout(pausacomprador10, 28000);
    setTimeout(pausacomprador11, 32000);
    setTimeout(pausacomprador12, 34000);
    setTimeout(pausacomprador13, 37000);
    setTimeout(pausacomprador14, 40000);
    setTimeout(pausacomprador15, 43000);
    setTimeout(pausacomprador16, 46000);
    setTimeout(pausacomprador17, 48000);
    setTimeout(pausacomprador18, 51000);
    setTimeout(pausacomprador19, 53000);

    Second Frame
    ———————————————————————-
    import mx.transitions.*;
    import mx.transitions.easing.*;

    stop();

    my_sound_2.stop();
    my_sound.stop();

    my_sound_3.loadSound(“audio/vendedor fase um.mp3″,true);

    next_mc.onPress = function()
    {
    TransitionManager.start(next_mc, {type:Fade, direction:Transition.OUT, duration:1, easing:Strong.easeIn});
    nextFrame();
    };

    prev_mc.onPress = function()
    {
    prevFrame();
    };

    TransitionManager.start(next_mc, {type:Fade, direction:Transition.OUT, duration:1, easing:Strong.easeIn});
    TransitionManager.start(prev_mc, {type:Fade, direction:Transition.OUT, duration:1, easing:Strong.easeIn});

    vendedor_0._visible = false;
    vendedor_1._visible = false;
    vendedor_2._visible = false;
    vendedor_3._visible = false;
    vendedor_4._visible = false;
    vendedor_5._visible = false;
    vendedor_6._visible = false;
    vendedor_7._visible = false;
    vendedor_8._visible = false;
    vendedor_9._visible = false;
    vendedor_10._visible = false;
    vendedor_11._visible = false;
    vendedor_12._visible = false;
    vendedor_13._visible = false;
    vendedor_14._visible = false;

    function pausa()
    {
    TransitionManager.start(vendedor_0,{type:Fade, direction:Transition.IN, duration:1, easing:Strong.easeIn});
    }
    function pausa2()
    {
    TransitionManager.start(vendedor_1,{type:Fade, direction:Transition.IN, duration:1, easing:Strong.easeIn});
    }
    function pausa3()
    {
    TransitionManager.start(vendedor_2,{type:Fade, direction:Transition.IN, duration:1, easing:Strong.easeIn});
    }
    function pausa4()
    {
    TransitionManager.start(vendedor_3,{type:Fade, direction:Transition.IN, duration:1, easing:Strong.easeIn});
    }
    function pausa5()
    {
    TransitionManager.start(vendedor_4,{type:Fade, direction:Transition.IN, duration:1, easing:Strong.easeIn});
    }
    function pausa6()
    {
    TransitionManager.start(vendedor_5,{type:Fade, direction:Transition.IN, duration:1, easing:Strong.easeIn});
    }
    function pausa7()
    {
    TransitionManager.start(vendedor_6,{type:Fade, direction:Transition.IN, duration:1, easing:Strong.easeIn});
    }
    function pausa8()
    {
    TransitionManager.start(vendedor_7,{type:Fade, direction:Transition.IN, duration:1, easing:Strong.easeIn});
    }
    function pausa9()
    {
    TransitionManager.start(vendedor_8,{type:Fade, direction:Transition.IN, duration:1, easing:Strong.easeIn});
    }
    function pausa10()
    {
    TransitionManager.start(vendedor_9,{type:Fade, direction:Transition.IN, duration:1, easing:Strong.easeIn});
    }
    function pausa11()
    {
    TransitionManager.start(vendedor_10,{type:Fade, direction:Transition.IN, duration:1, easing:Strong.easeIn});
    }
    function pausa12()
    {
    TransitionManager.start(vendedor_11,{type:Fade, direction:Transition.IN, duration:1, easing:Strong.easeIn});
    }
    function pausa13()
    {
    TransitionManager.start(vendedor_12,{type:Fade, direction:Transition.IN, duration:1, easing:Strong.easeIn});
    }
    function pausa14()
    {
    TransitionManager.start(vendedor_13,{type:Fade, direction:Transition.IN, duration:1, easing:Strong.easeIn});
    }
    function pausa15()
    {
    TransitionManager.start(vendedor_14,{type:Fade, direction:Transition.IN, duration:1, easing:Strong.easeIn});
    TransitionManager.start(next_mc,{type:Fade, direction:Transition.IN, duration:1, easing:Strong.easeIn});
    TransitionManager.start(prev_mc,{type:Fade, direction:Transition.IN, duration:1, easing:Strong.easeIn});
    }

    setTimeout(pausa,400);
    setTimeout(pausa2,3000);
    setTimeout(pausa3,6000);
    setTimeout(pausa4,9000);
    setTimeout(pausa5,11000);
    setTimeout(pausa6,15000);
    setTimeout(pausa7,19000);
    setTimeout(pausa8,23000);
    setTimeout(pausa9,25000);
    setTimeout(pausa10,29000);
    setTimeout(pausa11,33000);
    setTimeout(pausa12,38000);
    setTimeout(pausa13,40000);
    setTimeout(pausa14,42000);
    setTimeout(pausa15,44000);

  24. Gabriel says:

    It Functions!, but:

    How do i do to use textField instead trace?, this is to \print\ output!.

    Thanks!

  25. teretz says:

    OMG… too funny. I usually dont post. I’m a webdev, and was looking over Lee Brimelow as a quick refresher. I saw Andre Paz Leal’s post, which took up almost half the scrollbar, and had to laugh. Hey, did you answer that one, Lee?

    Cheers.

  26. Abbas says:

    jesus man, please don’t post a 500 line code in the comments section. use pastebin for that :|

  27. Andre says:

    Sorry friends, my solution was to use variables like this:

    var pausa:Number = setTimeout(pausa,400);

    And on the next and previous button place the clearTimeout(pausa);

  28. Andre says:

    And yeah now I see how long was my post, damn dumb…!!!

  29. You could delete the bigger post since you delete this, that question I found the solution but this one I haven´t ehehehe…

  30. karthikeyan says:

    I am new for flex i didn’t know action & java script but i want to do clock like in windows vista gadgets bar & i want to do slider show also so please help me to do.

  1. [... In previous version of ActionScript there were a couple of different ways to trigger events based on time. The setInterval() and setTimeout() functions were the two most commonly used ways ...]

  2. [... In previous version of ActionScript there were a couple of different ways to trigger events based on time. The setInterval() and setTimeout() functions were the two most commonly used ways ...]

  3. [... In previous version of ActionScript there were a couple of different ways to trigger events based on time. The setInterval() and setTimeout() functions were the two most commonly used ways ...]

  4. [... In previous version of ActionScript there were a couple of different ways to trigger events based on time. The setInterval() and setTimeout() functions were the two most commonly used ways ...]

  5. [... In previous version of ActionScript there were a couple of different ways to trigger events based on time. The setInterval() and setTimeout() functions were the two most commonly used ways ...]

Leave a Comment