Previous Page
Next Page

Recipe 1.12. Repeating a Task over Time

Problem

You want to perform some action or actions over time.

Solution

Use the Timer class. Alternatively, listen for the enterFrame event of a sprite.

Discussion

The Timer class is new to ActionScript 3.0, and is recommended over the earlier setInterval( ) and setTimeout( ) functions. When you create an instance of the Timer class, it fires timer events at regular intervals. You can specify the delay between events and how many times you want the events to fire in the Timer constructor:

var timer:Timer = new Timer(delay, repeatCount);

You use addEventListener to set up a method to handle these events. After you create the timer and set up a listener, use its start( ) method to start it and stop( ) to stop it.

The Timer class is part of the flash.utils package, and there is also a TimerEvent class in the flash.events package, so those need to be imported:

package {
    import flash.display.Sprite;
    import flash.events.TimerEvent;
    import flash.utils.Timer;
    
    public class ExampleApplication extends Sprite {
        // Declare and initialize a variable to store the value
        // of the previous timer reading.
        private var _PreviousTime:Number = 0;
        
        public function ExampleApplication(  ) {
            var tTimer:Timer = new Timer(500, 10);
            tTimer.addEventListener(TimerEvent.TIMER, onTimer);
            tTimer.start(  );
        }
        
        private function onTimer(event:TimerEvent):void {
            // Output the difference between the current timer value and
            // its value from the last time the function was called.
            trace(flash.utils.getTimer(  ) - _PreviousTime);
            _PreviousTime = flash.utils.getTimer(  ); 
        }
    }
}

The getTimer( ) function (previously a top-level function), has been moved to the flash.utils package as well. This simply returns the number of milliseconds since the application started.

In the preceding example, even though the interval is theoretically 500 milliseconds in practice its accuracy and granularity depend on computer playback performance in relation to other tasks demanded of the processor. There are two implications to this:

  • Don't rely on timers to be extremely precise.

  • Don't rely on timer intervals to be smaller than approximately 10 milliseconds.

If you want to emulate the functionality of the setInterval( ) function, set the repeat count to zero. This causes the timer event to fire indefinitely. In this case, the stop( ) method is analogous to the clearInterval( ) function, and stops the timer from firing further events.

Similarly, if you want to duplicate the setTimeout( ) function, set the repeat count to one. The timer waits the specified amount of time, fires one event, and ends.

One of the neat things you can do with the Timer class is create animations that are independent of the movie's frame rate. With a timer you can call a method at any interval you want. Here is an example in which two timers are setone for a square sprite (every 50 milliseconds)and one for a circle sprite (every 100 milliseconds):

package {
    import flash.display.Sprite;
    import flash.events.TimerEvent;
    import flash.utils.Timer;
    
    public class ExampleApplication extends Sprite {
        private var _square:Sprite;
        private var _circle:Sprite;
        
        
        public function ExampleApplication(  ) {
            // Create the two sprites and draw their shapes
            _square = new Sprite(  );
            _square.graphics.beginFill(0xff0000);
            _square.graphics.drawRect(0, 0, 100, 100);
            _square.graphics.endFill(  );
            addChild(_square);
            _square.x = 100;
            _square.y = 50;
            
            _circle = new Sprite(  );
            _circle.graphics.beginFill(0x0000ff);
            _circle.graphics.drawCircle(50, 50, 50);
            _circle.graphics.endFill(  );
            addChild(_circle);
            _circle.x = 100;
            _circle.y = 200;
            
            // Create the two timers and start them
            var squareTimer:Timer = new Timer(50, 0);
            squareTimer.addEventListener(TimerEvent.TIMER, onSquareTimer);
            squareTimer.start(  );
            
            var circleTimer:Timer = new Timer(100, 0);
            circleTimer.addEventListener(TimerEvent.TIMER, onCircleTimer);
            circleTimer.start(  );
        }
        
        // Define the two handler methods
        private function onSquareTimer(event:TimerEvent):void {
            _square.x++;
        }
        
        private function onCircleTimer(event:TimerEvent):void {
            _circle.x++;
        }
    }
}

It is also possible to use the enterFrame event of a sprite to have some action (or actions) repeat over time. The Timer technique offers some advantages over the enterFrame event method, most notably that it allows you to create intervals that differ from the frame rate of the .swf. With enterFrame, the handling method is called at the frame rate.

With that said, there are still times when using enterFrame is appropriate. For example, you may want something to occur at the frame rate of the .swf. One such scenario is when you want to reverse the playback of the frames in a movie clip.


Previous Page
Next Page
Converted from CHM to HTML with chm2web Pro 2.85 (unicode)