iducationducation
IndexArticlesFormationsProfilOutilsBibliothech
N°014 — 2026
Navigation
01Index02Articles03Formations04Profil05Outils06Bibliothech
N°014 — 2026
iducationducation
IndexArticlesFormationsProfilOutilsBibliothech
N°014 — 2026
Navigation
01Index02Articles03Formations04Profil05Outils06Bibliothech
N°014 — 2026
Formations
JavaScript · Débutant

Phaser

Créer un jeu de plateforme complet avec Phaser 4 : scènes, textures générées, tilemap, physique Arcade, animations, ennemis, particules, sons, UI, mobile et déploiement.

Phaser 4JavaScriptViteArcade PhysicsWeb Audio
01Introduction et installation02Scènes, textures générées et menu03Tilemap, niveau et caméra04Le joueur : physique Arcade, clavier et animations05Pièces, pics et ennemis : groupes et collisions06Game feel : particules, événements, caméra et son07Interface, chronomètre, pause et fin de partie08Mobile, build et mise en ligne
Chapitre 8·30 min

Mobile, build et mise en ligne

Un jeu web a un avantage énorme sur un jeu natif : on l'envoie par lien, et il se lance sur n'importe quel appareil. Encore faut-il qu'il s'affiche bien sur un téléphone et qu'on puisse y jouer sans clavier. Ce chapitre ajoute les contrôles tactiles, explique l'adaptation à l'écran, produit la version optimisée et la met en ligne.

L'adaptation à l'écran : le Scale Manager

Dans la configuration du chapitre 1 :

scale: {
  mode: Phaser.Scale.FIT,
  autoCenter: Phaser.Scale.CENTER_BOTH,
},

Le jeu garde sa résolution logique de 960 × 540 : toutes les positions du code restent valables. Le Scale Manager agrandit ou réduit le canvas pour remplir le conteneur, en conservant les proportions, et le centre.

ModeComportement
FITtout le jeu est visible, bandes noires si le ratio diffère
ENVELOPremplit tout l'écran, une partie du jeu peut être coupée
RESIZEle canvas prend la taille de l'écran ; à vous de replacer les éléments
NONEtaille fixe

FIT est le choix le plus simple et le plus sûr. Avec RESIZE, il faut écouter this.scale.on('resize', ...) et repositionner l'interface : plus de travail, pour un résultat sans bandes noires.

Sur mobile, un jeu en 16/9 se joue en paysage. On peut détecter l'orientation avec this.scale.orientation et afficher un message « tournez votre téléphone » quand elle vaut Phaser.Scale.PORTRAIT. Le passage en plein écran se fait avec this.scale.startFullscreen(), à appeler depuis un clic ou un toucher.

Les contrôles tactiles

Sur un appareil tactile, la scène UI affiche trois boutons. Ils écrivent dans un objet partagé via le registry, que le joueur lit dans son preUpdate depuis le chapitre 4.

src/scenes/UIScene.js
  creerControlesTactiles() {
    const { width, height } = this.scale
    const etat = { gauche: false, droite: false, saut: false, sautPresse: false }
    this.registry.set('tactile', etat)
    this.input.addPointer(2)
 
    const bouton = (x, y, libelle, appui, relache) => {
      const zone = this.add.circle(x, y, 46, 0xffffff, 0.2).setInteractive()
      this.add.text(x, y, libelle, { fontSize: '32px', color: '#ffffff' }).setOrigin(0.5)
      zone.on('pointerdown', appui)
      zone.on('pointerup', relache)
      zone.on('pointerout', relache)
    }
 
    bouton(80, height - 80, '◀', () => (etat.gauche = true), () => (etat.gauche = false))
    bouton(190, height - 80, '▶', () => (etat.droite = true), () => (etat.droite = false))
    bouton(width - 90, height - 80, '▲', () => {
      etat.saut = true
      etat.sautPresse = true
    }, () => (etat.saut = false))
  }

Remettez à la fin de UIScene.create la ligne retirée au chapitre 7 :

if (this.sys.game.device.input.touch) this.creerControlesTactiles()

Les notions utilisées :

  • setInteractive() rend un objet cliquable ou touchable. Il émet ensuite pointerdown, pointerup, pointerover, pointerout
  • pointerout relâche le bouton si le doigt glisse en dehors : sans lui, le personnage continuerait à courir indéfiniment
  • this.input.addPointer(2) : Phaser gère un seul point de contact par défaut. En ajoutant deux pointeurs, on peut courir et sauter en même temps avec deux doigts
  • sautPresse reproduit le comportement de JustDown : le bouton le met à true, le joueur le consomme et le remet à false. Ainsi le tampon de saut et le coyote time fonctionnent aussi au doigt
  • this.sys.game.device décrit l'appareil : tactile, système, navigateur, support audio. On n'affiche les boutons que là où ils servent
Jeu avec trois boutons ronds semi-transparents : gauche et droite en bas à gauche, saut en bas à droite
Les contrôles tactiles, affichés seulement sur les appareils tactiles.

Pour tester sans téléphone, les outils de développement de Chrome ont un mode appareil (Ctrl+Shift+M) qui simule le tactile. Rechargez la page après l'avoir activé : la détection se fait au démarrage.

Pour tester sur un vrai téléphone connecté au même réseau :

npx vite --host

Vite affiche une adresse réseau (http://192.168.x.x:5173) à ouvrir sur le téléphone.

Le mode debug, une dernière fois

Avant de publier, jouez une partie complète avec ?debug dans l'URL. Les corps physiques affichés révèlent les hitbox mal ajustées, les objets qui ne sont pas là où on les croit et les ennemis qui se coincent. C'est le test le plus rentable de tout le développement.

Surveillez aussi les performances : this.game.loop.actualFps donne le nombre réel d'images par seconde. Sur un téléphone d'entrée de gamme, restez au-dessus de 50.

La version de production

npm run build
dist/index.html                  0.52 kB
dist/assets/index-xxxx.js    1,390.99 kB │ gzip: 363.16 kB
✓ built
(!) Some chunks are larger than 500 kB after minification.

Le dossier dist/ contient tout le jeu : un HTML, un JavaScript minifié, et une copie de public/ (le niveau JSON). L'avertissement de taille est normal : Phaser pèse environ 1,4 Mo minifié, 360 Ko compressé, ce qui est ce que télécharge réellement le joueur. On peut masquer l'avertissement :

vite.config.js
import { defineConfig } from 'vite'
 
export default defineConfig({
  base: './',
  build: {
    chunkSizeWarningLimit: 1500,
  },
})

base: './' rend tous les chemins relatifs : le jeu fonctionne aussi bien à la racine d'un domaine que dans un sous-dossier comme https://exemple.fr/jeux/star-runner/.

Vérifiez la version de production localement avant de la publier :

npm run preview

Mettre en ligne

Le jeu est un site statique : n'importe quel hébergement de fichiers convient.

HébergementMéthodePour
itch.iozipper dist/, envoyer comme « HTML »la vitrine des jeux indépendants, avec communauté
GitHub Pagespousser dist/ sur une branche ou via une actiongratuit, lié au dépôt
Netlify, Vercel, Cloudflare Pagesglisser-déposer dist/ ou connecter le dépôtdéploiement automatique à chaque push
Votre serveurcopier dist/ derrière Nginx ou Caddycontrôle total

Pour itch.io, le fichier index.html doit être à la racine du zip, d'où l'importance de base: './'.

Sur votre propre serveur, un bloc Nginx minimal suffit, avec la compression activée pour réduire le poids de Phaser. La configuration détaillée est dans le guide installer et configurer Nginx.

server {
    listen 80;
    server_name jeu.exemple.fr;
    root /var/www/star-runner;
    index index.html;
 
    gzip on;
    gzip_types application/javascript application/json;
 
    location /assets/ {
        expires 1y;
        add_header Cache-Control "public, immutable";
    }
}

Les fichiers de assets/ ont un hash dans leur nom : on peut les mettre en cache un an, chaque nouvelle version change le nom. Pour publier automatiquement à chaque git push, le principe est expliqué dans GitHub Actions pour la CI/CD.

Aller plus loin

Le jeu est complet et en ligne. Pistes pour continuer, du plus simple au plus ambitieux :

  1. Un deuxième niveau : un nouveau JSON dans public/levels/, chargé dans Preload, et un passage au niveau suivant dans victoire au lieu de l'écran de fin
  2. De vrais graphismes : une spritesheet libre de droits chargée avec this.load.spritesheet, les clés de texture restent les mêmes
  3. Un nouvel ennemi : une chauve-souris qui vole en sinusoïde (allowGravity: false et un tween sur y), ou qui fonce vers le joueur quand il est proche (Phaser.Math.Distance.Between)
  4. Des bonus : un champignon qui rend une vie, une étoile qui rend invincible dix secondes
  5. Des niveaux conçus dans Tiled avec plusieurs calques et des objets
  6. De la musique, avec un fondu entre le menu et le jeu

Chacune de ces évolutions réutilise uniquement des notions vues dans ce cours.

Télécharger le projet complet

Le projet final de la formation, identique au code des chapitres, est disponible en archive. Il suffit de l'extraire puis de lancer npm install et npm run dev.

Star Runner — projet completCode source du jeu, niveau JSON, configuration Vite et README. Sans node_modules.ZIP · 19 Ko · Phaser 4

Un Scale Manager en mode FIT, trois boutons tactiles qui imitent le clavier, un npm run build et un dossier dist/ à déposer n'importe où : un jeu Phaser se publie aussi simplement qu'un site web. Vous avez maintenant un jeu complet, et surtout une architecture de scènes, d'objets et d'événements sur laquelle construire les suivants.

Précédent
Interface, chronomètre, pause et fin de partie

Développeur fullstack passionné. J'apprends en construisant et je documente tout — front, back, outils. Le code s'apprend mieux en public.

Naviguer

IndexTous les articlesFormationsProfilOutilsBibliothech

Ailleurs

GitHub RSS

Newsletter

Les articles, libs et découvertes. Une fois par semaine, pas plus.

© 2026 William LoreeConçu & codé à la main