3 votes

Le temps d'appel de RequestAnimationFrame change en fonction de la taille de mon canevas

Sur mon application, j'ai un canevas dont la taille CSS (CSS, pas html) est mise à jour en fonction de la taille de la fenêtre.

J'ai une boucle principale de gameplay qui ressemble à ceci :

run = function(){

    console.log(timerDiff(frameTime));

    game.inputManage();
    game.logics();
    game.graphics.animate();
    game.graphics.render();

    frameTime = timerInit();

    requestAnimFrame(run);

}

Ma fonction requestAnimFrame est celle de Paul Irish :

window.requestAnimFrame = (function(){
  return  window.requestAnimationFrame       || 
          window.webkitRequestAnimationFrame || 
          window.mozRequestAnimationFrame    || 
          window.oRequestAnimationFrame      || 
          window.msRequestAnimationFrame     || 
          function( callback ){
            window.setTimeout(callback, 1000 / 60);
          };
})();

En gros, le problème est que le timer que j'enregistre et qui mesure le temps écoulé entre l'appel à requestAnimFrame et l'appel à la fonction effective change du tout au tout. Si mon navigateur est en plein écran, j'obtiens 50/60 ms, et si j'ai une petite fenêtre, je peux atteindre quelque chose comme 10 ms.

Comme l'appel à requestAnimFrame est supposé appeler constamment la fonction sous un rythme de 60fps (ce qui est quelque chose comme 30 ms je pense) je ne devrais pas avoir ce genre de résultat, puisqu'il n'y a pratiquement rien qui se passe entre la création du timer et sa vérification, à part l'appel à requestAnimFrame

J'ai également des micro-gels récurrents (moins d'une seconde) qui se produisent toutes les 2/3 secondes. Mais le timer ne détecte aucun changement dans le temps (comme si le compteur de temps de javascript était bloqué).

Les fonctions de mes minuteries sont les suivantes, mais cela n'a pas vraiment d'importance ici

timerInit = function()
{
    return new Date();
}

timerDiff = function(datePrev)
{
    return new Date().getTime() - datePrev.getTime();
}

7voto

Jeffrey Sweeney Points 3052

En fait, la norme dit essentiellement que requestAnimationFrame fera "de son mieux" pour fonctionner à une fréquence d'images "constante". Cela ne garantit pas une fréquence de 60 images par seconde, mais indique simplement que l'animation sera aussi rapide que possible.

Mon expérience a été aussi faible que la vôtre jusqu'à présent, malheureusement. J'ai fini par revenir à setTimeout . Il avance à peu près au même rythme et les mises à jour graphiques sont précises et ne sautent pas de rythme comme c'était le cas avec requestAnimationFrame . Certes, ce n'était pas du 60fps, mais au moins on pouvait voir ce qui se passait.

Je suis certain que les performances s'amélioreront au fur et à mesure que les développeurs de navigateurs optimiseront la nouvelle fonction, mais pour l'instant, vous pouvez revenir à timeouts .

Edit : Je voudrais rappeler que la réponse à cette question a été donnée il y a un an, et que les temps ont changé :)

4voto

bogdan Points 374

"Le problème est que le timer que j'enregistre et qui mesure le temps écoulé entre l'appel à requestAnimFrame et l'appel à la fonction effective change totalement..."

Bien sûr que oui, c'est pourquoi vous devez la mesurer et vous baser sur cette valeur de différence de temps pour calculer votre prochaine image.

Supposons que vous souhaitiez animer la propriété css "left" d'une div de 0px à 120px en 1 seconde à 60 fps.

  • en utilisant setTimeout Comme c'est VOUS qui fixez le nombre d'images, vous savez de combien vous devez incrémenter la propriété "left" : 120px/60 images = 2px/image

  • à l'aide de requestAnimationFrame L'idée est qu'au début de l'animation, vous ne pouvez pas avoir une valeur fixe et prédéterminée à incrémenter à chaque image, vous devez la calculer dynamiquement sur la base de la différence de temps.

Ainsi, même si l'animation ne se déroule pas à la vitesse annoncée de 60 images par seconde, si des images sont sautées, chaque image qui n'est pas sautée dessinera la situation actualisée exacte.

Il faut un peu de doigté pour décider quand l'animation doit se terminer.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X