Something that has always puzzled me, and still does to this day, is why can the Timer class in AS3 not update fast enough for the lower millisecond numbers?
I seem to recall reading that Flash is capable of pushing an update to the Timer once every 20 milliseconds at the maximum (recommended) – The timer that I have created for a recent game updates every 50 milliseconds, but even that is struggling. Locally it works fine, in an online environment, it does not.
Is there something specific I’m doing wrong here, or is Flash just really not capable of updating fast enough in an online environment to do a two decimal place number of a second?
Again, this works fine locally.
My code for the timer is here:
package src.gameShared {
import flash.display.Sprite;
import flash.utils.Timer;
import flash.events.TimerEvent;
import src.main;
public class timer extends Sprite {
private var _updateAmount:int = 50; // MUST give a whole number if divided by 1000 and less than 100. Recommended above 20. Gives 25, 40 or 50.
private var _timer:Timer = new Timer(_updateAmount,0);
private var _count:int = new int();
public function startTimer():void{
_timer.addEventListener(TimerEvent.TIMER, updateText, false, 0, true);
_timer.start();
}
public function stopTimer():void{
_timer.stop();
// Add to score
}
private function updateText(e:TimerEvent):void{
_count++
dtf_txt.text = returnTime();
}
// The below will display double minutes, double seconds and double milliseconds. Most math is based around the double milliseconds.
public function returnTime(_score:Boolean = false){
/*
** Minutes takes _count and divides it by (1000/50) = 20 (_updateAmount being 50), to give the value of 1 per second. If _count is 20, this has run 20 times and thus 1000 miliseconds have passed
** So the int can be set to 1. Minutes then checks to see if there is 60 of them (60 seconds).
** Seconds does the same, except it "caps" at 60 before resetting
*/
var _division:int = (1000/_updateAmount)
var minutes:int = Math.floor(_count /_division / 60);
// Second is 1000 miliseconds
var seconds:int = Math.floor(_count /_division) % 60;
var milseconds:int = new int();
/* After how many ticks is it a second. So at 50, 20 ticks would be 100 so 1 second, but _count would only show 20. So we *5 to get 100.
** 100 = max num we want, divided by (1000 (1sec) divided by _updateAmount)
** 100/(1000/50) = 5. 5*20 (number of ticks at 50milli per sec) = 100 = what we want
*/
var _getMil:Number = 100/(1000/_updateAmount) // 5 (20 lots of _updateAmount per second, we want an update on every tick. We do *5 as 20 updates fits into 100 that way)
// How many updates to fit into 1000 (1 sec), then divide it by 10 as we want a single digit result
var _getSmallMil:Number = (1000/_updateAmount)/10 // 2 (20 lots of _updateAmount per second, we only want an update every 2nd for the whole number, so we half _count)
_score == false ? milseconds = Math.floor(_count*_getMil) % 100 : milseconds = Math.floor(_count/_getSmallMil) % 10;
// Easier to read code that does the same thing but isn't dynamic:
// _score == false ? milseconds = Math.floor(_count*5) % 100 : milseconds = Math.floor(_count/2) % 10;
var secString:String = (seconds < 10) ? ("0" + String(seconds)) : String(seconds);
var minString:String = (minutes < 10) ? ("0" + String(minutes)) : String(minutes);
if(_score){
var milString:String = String(milseconds);
if(minutes >= 1){
var _holder:int = int(secString);
_holder = _holder + (minutes*60);
secString = String(_holder);
}
return secString+"."+milString;
}
else{
var milString:String = (milseconds < 10) ? ("0" + String(milseconds)) : String(milseconds);
return minString+":"+secString+":"+milString;
}
}
}
}
Timers are optimal for non-animated content; however, as a visual runtime it is logical not to compute beyond the frame rate.
Targeting 60 frames per second is a realistic ceiling.
There are great articles on the Flash elastic racetrack.
References