Avg. Rating 4.7

Problem

The delay between 2 events of the timer class depends on many factors ( fps, memory, played movie clip end i.e. ). The timeout set to property delay of timer class is only approximate so there needs to be a way to increase the accuracy of the timer.

Solution

My solution to increase the accuracy is to extend the timer class and force the timer to make more cycles depending of the custom property accurate. In this way the delay between 2 events of the timer will be set delay - + accurate /2. Because the rising of the event depends form many factors truly delay between 2 events is from: delay - accurate/2 to next fired event from flash player.

Detailed explanation

This is an example how can be implemented a timer class with accurate property. Note that is a "IS A" pattern.

package
{
 import flash.events.EventDispatcher;
 import flash.events.TimerEvent;
 import flash.utils.Timer;
 
 /**
  * ...
  * @author Kalin
  */
 public class AccurateTimer extends Timer 
 {
  private var m_delay:    Number = 0;
  private var m_lastTime:   Date;
  private var m_accuracy:   uint = 10;
  private var m_nCount:    uint;
  private var m_nCurrentCount: uint;
  
  
  override public function get delay():Number
  {
   return m_delay;
  }
  
  
  override public function set delay( value: Number ): void
  {
   m_delay = value;
  }
  
  
  override public function get currentCount(): int
  {
   return m_nCurrentCount;
  }
   
  
  override public function get repeatCount(): int
  {
   return m_nCount;
  }
   
  
  override public function set repeatCount( value: int ): void
  {
   m_nCount = value;
  }
  
  
  public function get accuracy():uint
  {
   return m_accuracy;
  }
  
  
  public function set accuracy( value: uint ): void
  {
   m_accuracy = value;
  }
  
  
  public function AccurateTimer( nDelay: Number, nCount: uint )
  {
   m_delay  = nDelay;
   m_nCount  = nCount;
   addEventListener( TimerEvent.TIMER,    ontmrTick,   false, 0, true );
   super( m_accuracy, 0 );
  }
 
  
  override public function start(): void
  {
   m_lastTime   = new Date();
   m_lastTime.time = new Date().time + m_delay;
   super.start();
  }
  
  
  override public function stop(): void
  {
   super.stop();
  }
  
  
  override public function reset(): void
  {
   m_nCount   = 0;
   m_nCurrentCount = 0;
   super.reset();
  }

  private function ontmrTick( evnt: TimerEvent ): void
  {
   var nNewTime: Date = new Date();
   
   if ( ( nNewTime.time > m_lastTime.time ) ||
     ( m_lastTime.time - nNewTime.time < m_accuracy / 2 ) ||
     ( nNewTime.time == m_lastTime.time ) )
   {
    m_lastTime.time = m_lastTime.time + m_delay;
    
    if ( 0 < m_nCount )
    {
     
     m_nCurrentCount = m_nCurrentCount + 1;
     
     if ( m_nCount == m_nCurrentCount )
     {
      dispatchEvent( new TimerEvent( TimerEvent.TIMER_COMPLETE ) );
      reset();
      evnt.stopImmediatePropagation();
     }
    }
   }
   else
   {
    evnt.stopImmediatePropagation();
   }
  }
 }
}

 

And this is a code into timeline to measure the delay between 2 events from the class:

var tmr: AccurateTimer = new AccurateTimer( 1000, 10 );
tmr.addEventListener( TimerEvent.TIMER, onTmr );
tmr.addEventListener( TimerEvent.TIMER_COMPLETE, ontmrC );
tmr.start();
var m_time: Date = new Date();
function onTmr( evnt: TimerEvent ): void
{
 var newTime: Date = new Date();
 trace( "Timer: ", newTime.time - m_time.time );
 m_time = newTime;
}
function ontmrC( evnt: TimerEvent ): void
{
 var newTime: Date = new Date();
 trace( "Complete: ",newTime.time - m_time.time );
 m_time = newTime;
}
The value of the accurate property must depent from the delay interval. By default the accurate of the class is 0.01s and this is a good value for small delays ( up to several minutes ). For a big delays ( above 10 minutes ) the value of the accurate property may be greater ( for example 1-2 s ).
Little  demonstration of the class   
This is a 10 delays betweens events with default accurate of the class: ( 10ms )
Timer:  1,011s
Timer:  1,000s
Timer:  1,000s
Timer:  1,001s
Timer:  1,000s
Timer:  1,000s
Timer:  0,985s
Timer:  1,000s
Timer:  1,015s
Timer:  0,985s
 
This is a 10 delay with accurate = 1ms
Timer:  1,012s
Timer:  1,000s
Timer:  1,000s
Timer:  1,000s
Timer:  1,000s
Timer:  1,000s
Timer:  1,000s
Timer:  1,000s
Timer:  1,000s
Timer:  1,000s
 
 Note that the event TIMER_COMPLETE is calculated in repeadCount ( if the timer must fire 3 event it will fire 2 TIMER events and TIMER_COMPLETE event ).

+
This work is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License. Permissions beyond the scope of this license, pertaining to the examples of code included within this work are available at Adobe.

Report abuse

Related recipes