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.
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.
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;
}
+