Je suis en train de créer un jeu (un shmup) et j'ai commencé à me poser des questions sur la précision des minuteurs dans ActionScript. Bien sûr, ils sont assez précis lorsque l'on veut chronométrer des choses de l'ordre de quelques secondes ou décisecondes, mais il semble que les performances soient plutôt médiocres lorsque l'on passe à des plages plus fines. Il est donc difficile de faire des choses comme un vaisseau spatial qui tire une centaine de lasers par seconde.
Dans l'échantillon suivant, j'ai testé la durée (en moyenne) des intervalles entre 1000 ticks de timer prévus pour 30ms. À chaque fois, les résultats sont de ~35-36ms. En diminuant le temps, j'ai trouvé que le plancher sur le délai de la minuterie était de ~16-17ms. Cela me donne une vitesse maximale de 60 images par seconde, ce qui est excellent visuellement mais signifie aussi que je ne peux pas tirer plus de 60 lasers par seconde :-(. J'ai fait ce test plusieurs fois à 100 et 1000 boucles, mais pour le test de 30 ms et le test de 1 ms, les résultats n'ont pas changé. J'imprime dans un textField à la fin parce que l'utilisation de trace() et le lancement du swf en mode débogage semblent affecter négativement le test. Je me demande donc ce qui se passe :
- Ce test est-il une mesure décente des performances de la classe Timer, ou mes résultats sont-ils discutables ?
- Ces résultats changeront-ils radicalement sur d'autres machines ?
Je comprends que cela dépend de la précision de la méthode getTimer(), mais les discussions que je trouve sur ce sujet portent généralement sur la précision de getTimer() sur des intervalles plus grands.
package
{
import flash.display.Sprite;
import flash.events.TimerEvent;
import flash.text.TextField;
import flash.utils.getTimer;
import flash.utils.Timer;
public class testTimerClass extends Sprite
{
private var testTimer:Timer = new Timer(30, 1000);
private var testTimes:Array = new Array();
private var testSum:int = 0;
private var testAvg:Number;
private var lastTime:int;
private var thisTime:int;
public function testTimerClass()
{
testTimer.addEventListener(TimerEvent.TIMER, step);
testTimer.addEventListener(TimerEvent.TIMER_COMPLETE, printResults);
lastTime = getTimer();
testTimer.start();
}
private function step(event:TimerEvent):void
{
thisTime = getTimer();
testTimes.push(thisTime - lastTime);
lastTime = thisTime;
}
private function printResults(event:TimerEvent):void
{
while (testTimes.length > 0)
{
testSum += testTimes.pop();
}
testAvg = testSum / Number(testTimer.repeatCount);
var txtTestResults:TextField = new TextField();
txtTestResults.text = testAvg.toString();
this.addChild(txtTestResults);
}
}
}
Je pense que la meilleure solution serait de dessiner plusieurs lasers dans la même image avec des positions différentes et d'éviter d'avoir plus d'un objet Timer.
edit : J'ai utilisé stage.frameRate pour changer le frameRate du rendu et j'ai fait le test sur plusieurs framerates mais il n'y a pas de changement.