Le moteur de jeu HTML5 PHASER

mis à jour le 30/01/2013

Présentation

Phaser est un framework dédié au développement de jeux HTML5 en 2D. Il est developpé et activement maintenu par la société anglaise Photon Storm fondée par Richard Davey, tombé dans la marmite du jeu vidéo et de la scène démo à l'époque de la glorieuse ère 8-bit.

Phaser est un framework HTML5, c'est à dire que les jeux développés ont vocation à être exécutés dans un navigateur web aussi bien d'un ordinateur de bureau ou d'un portable que d'un appareil mobile (tablette, smartphone). Le langage de programmation utilisé est donc Javascript ou TypeScript

Le marché des jeux HTML5 sur mobiles est en plein essor, aussi Phaser se focalise-t-il sur les performances à l'exécution dans les navigateurs de ces types d'appareil. Pour optimiser l'affichage et tirer partie de l'accélération matérielle des cartes vidéo, le rendu graphique est assuré par la couche WebGL du navigateur si elle est disponible et par le contexte 2D de Canvas sinon, sans que le développeur n'ait à se soucier des diverses plateformes sur lesquelles son code tournera.
En fait, Phaser intègre la très performante librairie Pixi.js de Mat Groves qui est un moteur de rendu 2D au travers de WebGL. WebGL, s'il est déjà majoritairement répandu dans les navigateurs des ordinateurs, commence seulement a être implémenté dans les navigateurs mobiles. L'expérience des utilisateurs accédant actuellement à la couche WebGL sera donc forcément toujours bien meilleure en termes de rapidité, fluidité, effets visuels, etc. Cependant, comme la tendance est à l'adoption de WebGL sur tous les types d'appareils à venir, Phaser propose déjà d'utiliser ce mode de rendu dès que le matériel le supporte.

Plateformes

Phaser est une libraire Javascript conçue pour fonctionner sur l'ensemble des principaux navigateurs aussi bien ceux des desktops que ceux des mobiles. Il suffit que le navigateur possède a minima le support de Canvas. Ainsi sur les ordinateurs classiques, il fonctionne sans problème sous Chrome, Firefox, Opera, Safari et Internet Explorer (version 9 ou supérieure). De même, il fonctionne sous Safari des mobiles Apple (iOS5 ou supérieur), sous Chrome et même dans le navigateur intégré des mobiles Android (version 2.2 et supérieure).

L'équipe de Photon Storm a de plus pu vérifier que Phaser tourne parfaitement sur les appareils Tizen et sur le wrapper HTML5 des Kindle. Elle s'emploie d'ailleurs à maintenir le framework à jour pour qu'il puisse fonctionner sur les nouveaux smartphones basés sur une architecture web qui sortent sur le marché. Enfin, elle a reçu de la fondation Mozilla un ensemble de smartphones Firefox OS qui lui ont permis de valider complètement le fonctionnement de Phaser sur ce système.

La société se consacre uniquement à deux activités : d'une part, développer et maintenir Phaser et, d'autre part, concevoir et vendre des jeux vidéos HTML5 ... basés évidemment sur Phaser.
Ce choix de ne produire qu'en HTML5 est délibéré alors que d'autres technologies permettent d'ores et déjà de produire des applications mobiles natives à travers des frameworks dédiés comme Unity, Corona, Titanium, etc. Le marché HTML5 est en effet extrêmement prometteur d'autant qu'il permet de s'affranchir des multiples "stores" de diffusion, les coûts de développement sont réduits (un code unique pour toutes les plateformes), la compétence est abondante (développeurs et documentation Javascript) et les wrappers HTML5 comme CocoonJS ou Ejecta permettent déjà d'encapsuler des jeux à la façon d'applications natives sur les mobiles avec des optimisations de rendu impressionnantes. Le support direct de CocoonJS et Node-Webkit est d'ailleurs bientôt prévu dans le core de la librairie.
C'est pourquoi la capacité de Phaser à fonctionner sur toutes les plateformes HTML5 est cruciale pour Photon Storm qui vend ses produits essentiellement via des portails de jeux web ou, encapsulés comme applications natives, via les "stores". C'est en ceci que Phaser essaie de se démarquer des autres très nombreux frameworks HTML5 qui voient le jour régulièrement : tout doit fonctionner dans le monde réel y compris sur les appareils mobiles, généralement bien moins dotés de ressources que les ordinateurs (moins de RAM, de CPU, de GPU, de connectivité, etc).

Sous le capot

Choisir un framework est pour un développeur un choix savant entre un ensemble des points : le langage utilisé, l'architecture du framework, les fonctionnalités et la documentation qu'il propose, sa capacité en prendre en compte ou non des formats externes, à composer avec plusieurs matériels ou périphériques et le support qu'il reçoit de la communauté qui l'utilise.

Voici donc quelques éléments de choix.

Langage et architecture

Le langage de programmation est, comme expliqué au début cet article, Javascript. Cependant, contrairement à d'autres frameworks de jeux HTML5, Phaser n'impose absolument rien, ni dans le code, ni dans la structure du code : pas pseudo-classes objet, pas agencement des entités ou des procédures selon un schéma impératif. Du Javascript pur et simple uniquement.

Ceci n'interdit évidemment pas à chacun d'utiliser une structuration forte, voire même d'utiliser des pseudo-classes ou les design patterns de son choix afin d'améliorer la maintenabilité et la lisibilité du code. Phaser ne l'impose simplement pas.

La structure de Phaser est relativement simple : une succession d'états (states) comme le chargement, le menu principal, les niveaux, etc, qui peuvent ou non lancer une boucle de jeu (game loop). Phaser n'implémente pas l'architecture Entité-Composants-Systèmes (ECS) en vogue dans le monde du développement de jeux mais il reste néanmoins possible d'y organiser le code dans ce sens (merci à ooflorent).

Certains développeurs reprochent à Javascript justement de manquer de structure, de contrôle de types ou de réelle orientation objet et lui préfèrent pour ces raisons le sur-ensemble TypeScript. Phaser propose donc un fichier de définitions TypeScript ainsi qu'un template de démarrage à ceux qui préfèreront cette alternative à Javascript.

Phaser est lui-même codé en Javascript. Le framework passe avant chaque sortie de version systématiquement au crible de JSHint, ce qui garantit une forte cohérence du code au sein de la communauté des contributeurs.

En résumé, développer un jeu avec Phaser, c'est coder en Javascript ou en TypeScript en utilisant le mode de structuration ou d'organisation du code de son choix (ou aucun).

Pré-chargement

Phaser propose un module Loader intégré. Ce type de module permet de charger entièrement ou partiellement depuis différents URLs (utile pour l'usage de CDN, à noter que Phaser lui-même est disponible depuis cdjns) un ensemble de ressources variées, telles que :

Le pré-chargement des ressources permet d'une part d'avoir la garantie que les ressources provenant de diverses origines sur le Web seront bien disponibles lorsque le code essaiera de les accéder et, d'autre part, d'afficher par exemple une barre de progression ou tout autre dispositif indiquant à l'utilisateur qu'il doit patienter.

L'affichage

L'élément Canvas du DOM HTML5 permet deux modes de rendu : le rendu en contexte 2D ou le rendu WebGL au travers de l'accélération matérielle proposée par la carte graphique, qu'elle soit en 2D ou en 3D. Phaser reste un moteur de jeu 2D, mais il s'appuie, dès qu'elle est disponible dans le navigateur, sur la couche WebGL et rétrograde en Canvas 2D sinon. À moins qu'il choisisse explicitement l'une ou l'autre, le développeur n'a donc pas à se soucier de la manière dont le framework effectue l'affichage, celui-ci choisit le mode optimal de la plateforme qui exécute le jeu.

Si quasiment l'ensemble des ordinateurs propose la couche WebGL, ce n'est pas encore le cas actuellement pour tous les navigateurs des mobiles. L'expérience de l'utilisateur sur un jeu exigeant en terme de rendu (vitesse, fluidité, effets) peut donc être différente selon la plateforme, ceci n'est d'ailleurs pas une problématique propre à Phaser. Cependant, la tendance des concepteurs d'appareils mobiles est maintenant à l'adoption large de WebGL dans les nouvelles versions des navigateurs, tendance déjà anticipée par Phaser de ce point de vue.

Dans les faits, Phaser n'implémente que la gestion complète du jeu (le calcul des positions, des collisions, la gestion des entrées, la game loop, etc) et s'appuie sur la très puissante librairie Pixi.js de Mat Groves, dédiée au rendu WebGL en 2D, pour tout ce qui concerne l'affichage. Ainsi certaines des fonctions de rendu de Phaser, si elles ne sont pas enrichies d'une logique propre au moteur de jeu, sont directement des fonctions Pixi.js.

Phaser se cale sur la fréquence de rafraichissement du navigateur, c'est à dire qu'il affiche 60 images par seconde, soit une image toutes les 16 ms. C'est donc au développeur de penser efficacement son code pour réaliser les traitements de la logique du jeu en moins de 16 ms par cycle. Encore une fois, ce n'est pas une problématique propre à Phaser mais au développement de jeux HTML5 en général : le développeur doit par exemple prendre en compte que, mode canvas ou webGL, dessiner des formes par la programmation est plus coûteux pour le GPU que placer des sprites à l'écran, que créer des objets Javascript non persistants risque de consommer beaucoup de temps de ramasse-miettes (garbage collector) qui peut se déclencher à un moment critique du jeu, etc.

Enfin, Phaser intègre un gestionnaire d'affichage qui permet l'adaptation à toutes les tailles d'écran, avec le respect du ratio largeur/hauteur et la capacité de basculer en mode plein-écran. L'intérêt pour le développeur est, encore une fois, de ne pas se soucier des diverses plateformes ou résolutions : il code son jeu dans une taille fixée, par exemple sur 800 x 600 pixels, et laisse Phaser l'adapter à l'appareil sur lequel il s'exécute.

Les sprites

Si le moteur de jeu est le cœur du système, les sprites en sont la sève.

Phaser permet donc de charger, de créer et d'animer des sprites, en utilisant les procédés décrits dans le pré-loader (sprite sheets, atlas, ...), mais aussi bien sûr de les déplacer -y compris à l'aide de comportements automatiques ou d'interpolations (tweens) -, de les redimensionner ou de les pivoter. Un sprite peut même être utilisé pour appliquer une texture dynamiquement à une image.

Phaser, comme la plupart des moteurs de jeu, gère évidemment les collisions entre sprites, entre groupes de sprites, ou avec des limites du monde du jeu, comme les tilemaps. Pour l'instant, cette gestion, même si elle est optimisée par l'usage d'un partitionnement QuadTree, est limitée au mode AABB. On regrette donc l'absence des modes de collision cercle-AABB et séparation des axes entre deux polygones ou entre un cercle et un polygone. Comme expliqué précédemment, dessiner des formes (polygones, cercles) est plus coûteux pour le GPU que de placer des sprites à l'écran, donc Phaser excelle pour l'instant dans la gestion des sprites avec une gestion des collisions très efficace en terme de performance -capital pour les mobiles-, mais peu riche en terme de possibilités. Photon Storm envisage d'intégrer très prochainement la librairie p2.js qui non seulement comblerait ce manque mais doterait aussi Phaser d'un moteur physique plus complet que l'actuel qui gère déjà les notions de vitesse, accélération, gravité, collision/séparation (AABB), rebond et frottement des sprites.

Phaser propose une gestion des sprites (et d'autres types d'objets) par groupes. Les groupes permettent d'effectuer des actions sur la collection complète des objets qui les composent (déplacement, détection d'une collision ou d'une superposition, etc) en très peu de lignes de code. Ils permettent surtout de créer et de maintenir les allocations en mémoire de ces objets, même s'ils ne sont plus utilisés (ex : un sprite ennemi vient d'être détruit), afin de pouvoir les recycler (ex : un nouvel ennemi apparaît) et optimiser ainsi le fonctionnement du garbage collector de la machine virtuelle Javascript. Le concept de groupe de sprites est donc central dans Phaser et est massivement utilisé par les développeurs des jeux.

Il est à noter que les sprites implémentent un gestionnaire d'évènements d'entrée, c'est à dire qu'ils peuvent réagir, au pixel de contact près, au clic de souris ou encore au toucher, à la pression ou au glissement du doigt sur un mobile.

Enfin, Phaser propose un système de particules basé sur les sprites. Chaque particule d'un émetteur de particules est un sprite, qui peut être différent des autres, soumis aux contraintes physiques de l'émetteur (nombre maximum de particules, vitesse, accélération, gravité, durée de vie des particules, collisions, etc). Le système se charge ici encore de de recycler les objets créés à la volée.

Les tilemaps

Les tilemaps sont des cartes ou des décors de jeu constitués par la répétition de quelques éléments graphiques de petite taille, les tiles. Tiled est un éditeur de tilemaps open source très populaire. Phaser peut importer des fichiers au format Tiled, au format CSV ou créer dynamiquement par le code une tilemap.

Le framework propose ensuite une gestion étendue de la tilemap utilisée : mise à jour des tiles en temps réel (échange, remplacement, création, suppression), gestion des collisions des sprites aux tiles, superposition de plusieurs couches, utilisation de plusieurs jeux de tiles par couche, déplacement de la tilemap en fonction des déplacements du joueur, etc. Le tout en seulement quelques lignes de code pour le développeur.

La caméra

Un jeu Phaser se déroule dans un monde qui peut largement dépasser la seule taille de l'écran. Ainsi des objets, des sprites, des tiles, peuvent être situés au delà de ce que voit le joueur et n'apparaître à l'écran que lorsque ce dernier s'en approche. Un système de caméra intégré permet de choisir la perspective donnée au jeu (caméra attachée au sprite du joueur ou à une zone), de se focaliser sur un objet précis ou un point, de suivre une cible ou de panoter sur le monde.

Le son

Comme pour WebGL, la plupart des navigateurs actuels implémentent l'API Audio HTML5, mais leurs anciennes versions pas forcément. Phaser s'adapte ici encore à la plateforme. Il sait même traiter les audio sprites, méthode qui consiste à enregistrer dans un même fichier toute une collection de sons et à jouer uniquement le son voulu en déplaçant le pointeur de lecture sur le fichier.

De façon concrète, Phaser propose au développeur de gérer les sons multi-canaux, le streaming, les boucles audio, le volume évidemment et le déverrouillage automatique du système audio des mobiles. Un effort particulier est d'ailleurs apporté dans la résolution des problématiques de son des mobiles au travers des remontées utilisateurs sur tout type d'appareils.

Les entrées utilisateurs

Les utilisateurs interagissent avec les jeux aux moyens de mécanismes d'entrées qui peuvent être le clavier, la souris, le joystick ou gamepad ou encore directement le contact avec l'écran pour les mobiles.

Phaser propose évidemment une gestion intégrée des entrées clavier. Les mouvements et les clics de la souris d'un ordinateur pouvant être reproduits par le mouvement des doigts sur l'écran d'un mobile, Phaser propose une classe d'abstraction nommée Pointer chargée de gérer aussi bien les entrées souris que les entrées tactiles. Le développeur n'écrit donc ici encore le code qu'une seule fois. Le joueur peut alors passer à la volée de la souris à l'écran tactile sans la moindre interruption. Par ailleurs, Phaser gère aussi le multi-touch et prend en compte jusqu'à dix points de contact indépendants sur l'écran.

Phaser ne propose pas pour l'instant de mécanisme intégré de gestion des joysticks ou gamepad. Le développeur doit donc faire appel à l'API Gamepad HTML5 si elle est disponible sur la plateforme où le jeu s'exécute. Néanmoins, Photon Storm prévoit d'inclure prochainement la prise en charge des joysticks et gamepads, vu que l'API commence à peine à être déployée dans les principaux navigateurs.

Les plugins

Photon Storm se focalise sur la stabilité de Phaser et sa compatibilité permanente avec l'ensemble des navigateurs. Aussi son noyau ne doit-il pas grossir au fil des ajouts de fonctionnalités propres à chaque type de jeu. C'est pourquoi Phaser propose un système de gestion de plugins.

Les plugins s'intègrent directement au framework et peuvent être pris en compte par la game loop du noyau, qui peut enrichir Phaser de fonctionnalités intéressantes comme un algorithme A* de recherche de chemin dans un graphe (plugin easystarjs).

Le support

Phaser est utilisé au quotidien dans la réalisation de jeux commerciaux, aussi est-il très fréquemment maintenu ne serait-ce que pour garantir sa compatibilité à tous les appareils, outre les classiques correctifs de bugs et autres optimisations. Photon Storm se targue de traiter très rapidement tous ces types de demandes, tout simplement parce qu'en tant que société commerciale établie, ils ne peuvent pas vendre des produits qui fonctionnent mal ou pas du tout à leurs clients.

Phaser évolue donc en permanence. Son dépôt github se compose uniquement de deux branches : master qui constitue la version stable en cours et dev, la version en cours de développement qui reçoit des commits quotidiens.

Le forum

Pour faire évoluer Phaser, Photon Storm a besoin du retour permanent des développeurs que ce soit au sujet de bugs, d'améliorations, d'ajouts de fonctionnalités, de performances, mais aussi et surtout de fonctionnement en situation réelle sur les matériels existants. C'est pourquoi le forum HTML5 Game Dev a été créé.

Ce forum est le lieu d'une intense activité. On y trouve pèle-mèle des retours de développeurs aussi bien sur le framework que sur l'expérience sur leur propre matériel, mais aussi des demandes d'aide sur certains points de programmation, des jeux exemples des uns et des autres, des conseils et carrément des requêtes techniques de correction ou amélioration qu'on s'attendrait plus à voir sur github. Les réponses y sont rapides et le contenu reste pertinent, il n'y a pas de discussion stérile sans fin ou d'échanges d'opinions irrémédiablement contradictoires. C'est ainsi que le forum fonctionne et cette communauté très active est réellement le point fort de Phaser en ce qui concerne le support.

Il est à noter que le forum HTML5 Game dev a été étendu à des thématiques plus larges que le simple framework Phaser. On y trouve les sujets suivants : news, démonstration de jeux HTML5 finis ou en cours (pas nécessairement réalisés avec Phaser), conception et programmation de jeux (tous langages, frameworks et librairies confondus), 2D, 3D, Audio, les frameworks Phaser, Pixi.js, Babylon.js et SpellJS et quelques thèmes sur les sponsors et portails de jeux ou les collaborations entre développeurs, webdesigner, musiciens, etc.

La documentation

Comme pour la plupart des frameworks de jeux HTML5 gratuits, la documentation de Phaser va se limiter à la présentation de l'API de programmation de la version stable en cours. Si l'APi est bien documentée, on peut regretter de n'avoir pas accès à une description formelle de l'architecture et des concepts mis en œuvre. Phaser s'apprend par l'exemple.

Le développeur novice est ainsi invité à lire attentivement le manuel de démarrage. Il peut ensuite s'entrainer sur un site d'exemples qui présente, non pas uniquement des jeux, mais des cas d'usage de l'ensemble des notions ou classes de l'API. Il peut aussi se lancer directement dans la réalisation d'un petit jeu complet à partir des tutoriaux mis en ligne par Photon Storm et d'autres contributeurs. Une liste non exhaustive est disponible en bas de cet article.

Le développeur plus chevronné se doit d'utiliser la documentation de l'API, soit dans sa version en ligne, soit dans la version intégrée de l'archive téléchargeable de Phaser. Cette archive contient de plus tous les exemples, leurs ressources (images, sprites, tiles, etc) ainsi que des templates de projets. Si le développeur a besoin de plus d'informations ou d'assistance, il doit alors se tourner vers le forum pour obtenir les réponses attendues des membres de la communauté.

Démarrer

Le plus simple étant de se faire une opinion par soi-même, il suffit de télécharger l'archive de Phaser et de la décompresser. L'archive, comme expliqué précédemment inclut beaucoup de choses (documentation, exemples, ressources, etc), mais le moteur Phaser est contenu dans un unique fichier nommé phaser.min.js placé dans le répertoire build de l'archive.

Il suffit d'importer ce fichier, via une balise <script>, dans une page HTML pour que Phaser y soit alors disponible. La lecture du manuel de démarrage complet est ensuite la meilleure méthode pour débuter.

Liens utiles

Notes

Image du logo de Phaser avec l'autorisation de Photon Storm.

Validation HTML W3C
Validation CSS W3C