Moteur JS : Game Loop et requestAnimationFrame
Une fonctionnalité qui unit tous les moteurs de jeu, est la Game Loop : une fonction qui gère le cycle du jeu ; la physique (la mise à jour de la position de nos éléments de jeu, le contrôle des collisions), et le Draw, des objets qui font partie du jeu (les GameObject).
requestAnimationFrame, gérer l’actualisation de la scène
En HTML5, la fonction requestAnimationFrame a été ajoutée pour remplacer l’ancienne méthode d’animation, qui utilisait un timer (setTimeout) pour afficher une image toutes les “quelques” millisecondes.
Avec requestAnimationFrame, nous pouvons indiquer au moteur JavaScript la fonction à lancer la prochaine fois qu’un frame est déclenchée. Voici la syntaxe :
<em>(request ID)</em> = requestAnimationFrame(<em>callback</em>)
Grace à cette fonction native, le navigateur peut optimiser le rendering nativement en gardant le framerate plus stable et fluide (avec un maximum de 60fps), ce qui réduit considérablement les « coups » ennuyeux qui ont été notées en utilisant le Timer (setTimeout, setInterval).
Dans le cas où un autre onglet du navigateur est ouvert, le rendering serait temporairement désactivé, contrairement à setTimeout, qui continuerait à fonctionner en utilisant la CPU, GPU et de la mémoir e: l’utilisation accrue de la performance du hardware, qui dans les appareils portables et mobiles, se résume à un gaspillage de batterie.
Un polyfill pour requestAnimationFrame
Vu que l’HTML5 n’était pas encore la norme en 2014, requestAnimationFrame a été mis en place temporairement par un préfixe dans l’identifiant (webkit, moz, ou, ms), qui fait référence aux différents noms de navigateur : nous définissons une fonction générique, un polyfill, qui renvoie l’identifiant de la fonction correcte.
Pour éviter d’avoir à appeler chaque fois toutes les possibles fonctions créons ce que l’on nomme un Polyfill, ou une fonction qui rappelle la fonction correcte pour chaque client.
Créons un nouveau fichier JavaScript (utils.js), dans lequel on va insérer toutes les fonctions pratiques que nous utiliserons dans notre framework. Commençons par ce polyfill :
window.requestAnimFrame = (function(callback) { return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function(callback) { window.setTimeout(callback, 1000 / 60); }; })();
Bien que la probabilité soit éloignée, nous pouvons avoir un navigateur qui ne supporte pas requestAnimationFrame, auquel cas notre fonction utilisera l’ancienne méthode setTimeout.
Pendant que nous y sommes, déplaçons l’event listener load de main.js vers utils.js
window.addEventListener('load', function() { StartGame(); },
Compatibilités
GameLoop
Nous pouvons enfin définir le GameLoop, c’est-à-dire la fonction qui nous permet de créer une boucle infinie dans laquelle on pourra gérer les animations et les événements frame après frame. Définissons la fonction GameLoop, à l’intérieur de l’objet Game :
function Game() { // ... choses définies dans la leçon précédente this.GameLoop = function() { if(!this.paused) { // mettre à jour tous les objets this.Update(); } // dessine toute la scène sur l'écran this.Draw(); window.requestAnimFrame(function() { // relance la fonction GameLoop sur chaque image game.GameLoop(); }); } }
Le cœur de la boucle est requestAnimFrame, dans lequel nous appelons à nouveau la fonction GameLoop de l’instance Game, de sorte qu’un mécanisme récursif est déclenché, dans lequel Update () et Draw () sont exécutés à chaque frame.
La plupart des frameworks de jeux vidéo prévoient que les objets du jeu (GameObject, que nous allons voir) ont des fonctions Update et Draw, ce qui en fait deux éléments fondamentaux du moteur et même s’ils ne sont pas encore définis, nous nous engageons à les définir rapidement.
On peut également définir la variable paused, qui bloquera la fonction Update lorsqu’elle est définie sur true.
Remarque : Draw () reste toujours actif, de manière à afficher quand même les images. Dans les chapitres suivants, nous verrons comment optimiser les performances pendant la pause en utilisant le canevas OffScreen.
➡️ Créer des jeux HTML5, le guide
Formations de Develop4fun
- Formation WordPress : le cours complet
- Parcours pour devenir un programmeur web
- Créez vos jeux avec UNITY3D
- Parcours pour devenir un programmeur de jeux vidéo
- Apprenez à créer des jeux 2D facilement avec LUA et LÖVE 2D
- Parcours pour devenir un programmeur de jeux vidéo
- Apprenez à programmer en C#
- Apprenez à programmer en C++
Étiquette :bases d'un game engine, Draw, GameObject, polyfill, requestAnimationFrame