Fabrique ton jeu vidéo, épisode 1 : ton premier truc qui bouge
Tous les jeux vidéo, du plus petit au plus gros, font la même chose soixante fois par seconde : effacer l'écran, calculer où sont les choses, les redessiner. C'est tout. Cet épisode te fait fabriquer cette mécanique en trente lignes, et tu vas t'en servir jusqu'à la fin de la série.
1. Ce que tu vas fabriquer Regarde d'abord, tu comprendras après
Voici le résultat de cet épisode. Un carré qui se déplace et qui rebondit sur les bords. Touche aux curseurs : tu changes ce que fait le programme pendant qu'il tourne.
Bouge les curseurs. Tout ce que tu modifies ici correspond à une ligne du code de la section 6.
La case « laisser une trace » enlève simplement l'effacement de l'écran. C'est le meilleur moyen de voir ce que la boucle fait vraiment.
2. Ce qu'il te faut Presque rien, et c'est voulu
1 Deux choses, et tu les as déjà
- Un navigateur. Celui avec lequel tu lis cette page fait parfaitement l'affaire.
- Un éditeur de texte. Le Bloc-notes suffit. Un éditeur de code est plus confortable parce qu'il colore le texte et repère tes fautes de frappe, mais ce n'est pas obligatoire pour commencer.
Rien à installer, rien à payer, pas de compte à créer. C'est la grande force du web pour apprendre : ton navigateur sait déjà tout faire.
2 Comment on travaille
- Tu crées un fichier qui s'appelle
jeu.html, quelque part où tu le retrouveras. - Tu colles le code dedans, tu enregistres.
- Tu double-cliques dessus : il s'ouvre dans le navigateur.
- Tu modifies, tu enregistres, tu recharges la page. C'est la boucle dans laquelle tu vas passer les prochaines heures.
Garde les deux fenêtres côte à côte, l'éditeur et le navigateur. Tu gagneras un temps fou.
3. La page de départ Le décor, avant les acteurs
Un jeu web, c'est une page comme les autres, avec une zone de dessin dedans. Cette zone s'appelle un canvas, ce qui veut dire « toile » en anglais. Voici la page la plus courte qui en contient une.
jeu.html, version 1
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8">
<title>Mon jeu</title>
<style>
body { background: #0f172a; display: grid; place-items: center; height: 100vh; margin: 0; }
canvas { background: #1e293b; border-radius: 8px; }
</style>
</head>
<body>
<canvas id="ecran" width="640" height="360"></canvas>
<script>
// tout notre code viendra ici
</script>
</body>
</html>
Enregistre, ouvre le fichier. Tu vois un rectangle gris sur fond bleu nuit. Il ne se passe rien, et c'est normal : la toile est posée, personne n'a encore dessiné.
Les deux nombres qui comptent
width="640" et height="360" définissent la taille de ta toile en pixels de dessin. C'est ta feuille de papier. Tout ce que tu dessineras se repère sur cette grille :
- Le point
(0, 0)est en haut à gauche, pas en bas à gauche comme en maths. xaugmente vers la droite,yaugmente vers le bas.- Le coin en bas à droite est donc
(640, 360).
Ce y à l'envers surprend tout le monde au début, y compris les gens qui codent depuis vingt ans. Retiens-le une fois, et tu ne te feras plus avoir : descendre, c'est augmenter y.
4. Dessiner Une feuille, et un crayon
La toile toute seule ne sert à rien. Il faut demander au navigateur un crayon pour dessiner dessus. Ce crayon s'appelle le contexte, et on le récupère en une ligne.
Dans la balise script
// On récupère la toile, puis le crayon qui va dessiner dessus. const ecran = document.getElementById('ecran'); const crayon = ecran.getContext('2d'); // On choisit une couleur, puis on remplit un rectangle. // Les quatre nombres : x, y, largeur, hauteur. crayon.fillStyle = '#38bdf8'; crayon.fillRect(50, 40, 30, 30);
Recharge : un carré bleu apparaît. Tu viens de dessiner ta première chose à l'écran.
Essaie tout de suite
- Change les deux premiers nombres. Le carré se déplace.
- Change les deux derniers. Il change de taille.
- Change la couleur. Essaie
'red','#ff00ff','orange'. - Copie la ligne
fillRectet colle-la trois fois avec des nombres différents. Tu as trois carrés.
Ne lis pas la suite avant d'avoir fait ces quatre choses. Cinq minutes de bidouille valent mieux que trois pages d'explication.
Le crayon sait faire autre chose
fillRectremplit un rectangle,strokeRectn'en trace que le contour.fillText('Salut', 20, 30)écrit du texte.arcdessine un cercle, mais il demande un peu plus de code.drawImagecolle une image, et c'est comme ça qu'on affichera de vrais personnages plus tard.
Pour toute cette série, le rectangle suffira. Un jeu se fabrique avec des rectangles, on met les jolis dessins par-dessus à la fin.
5. La boucle de jeu Le cœur de tout, et ça tient en six lignes
Un jeu vidéo ne bouge pas. Il redessine.
Soixante fois par seconde, il efface tout, recalcule où sont les choses, et les redessine un peu plus loin. Ton œil fait le reste et croit voir un mouvement. C'est exactement le principe du dessin animé.
clearRect
On repart d'une toile vide
x = x + vitesse
Où sont les choses maintenant ?
fillRect
On les repose à leur nouvelle place
requestAnimationFrame
Dans un soixantième de seconde
La quatrième étape utilise une fonction du navigateur qui veut dire, en gros : « rappelle-moi juste avant le prochain affichage ». C'est le navigateur qui décide du bon moment, et c'est bien mieux que de compter soi-même.
La boucle, dans sa forme minimale
function tour() { // 1. effacer toute la toile crayon.clearRect(0, 0, ecran.width, ecran.height); // 2. calculer (pour l'instant, rien) // 3. dessiner crayon.fillStyle = '#38bdf8'; crayon.fillRect(50, 40, 30, 30); // 4. recommencer au prochain affichage requestAnimationFrame(tour); } tour(); // on lance le premier tour
Recharge. Visuellement, rien n'a changé : le carré est toujours au même endroit. Mais il est maintenant redessiné soixante fois par seconde. Il ne reste qu'à le déplacer un peu à chaque tour.
6. Faire bouger Position, vitesse, et le piège du temps
Pour qu'une chose bouge, il lui faut deux informations : où elle est (sa position) et de combien elle avance (sa vitesse). À chaque tour, on ajoute la seconde à la première.
jeu.html, version qui bouge
const ecran = document.getElementById('ecran'); const crayon = ecran.getContext('2d'); // Notre carré : sa position, sa taille, sa vitesse. const carre = { x: 50, y: 40, taille: 30, vx: 3, vy: 2 }; function tour() { crayon.clearRect(0, 0, ecran.width, ecran.height); // on avance carre.x += carre.vx; carre.y += carre.vy; crayon.fillStyle = '#38bdf8'; crayon.fillRect(carre.x, carre.y, carre.taille, carre.taille); requestAnimationFrame(tour); } tour();
Recharge : le carré part en diagonale et disparaît par le coin. C'est ton premier mouvement, et il fonctionne. On règle la sortie d'écran à la section suivante.
! Le piège que tout le monde se prend
Écrit comme ça, ton jeu va plus ou moins vite selon l'écran. Un écran de téléphone récent affiche 120 images par seconde, un vieil ordinateur 60 : sur le premier, ton carré ira deux fois plus vite. Ce n'est pas un détail, c'est ce qui rend un jeu injouable sur la machine d'un copain.
La solution : ne plus raisonner en « pixels par image » mais en pixels par seconde, et multiplier par le temps réellement écoulé depuis le tour précédent.
La version qui va à la même vitesse partout
// Vitesse en pixels PAR SECONDE, pas par image. const carre = { x: 50, y: 40, taille: 30, vx: 180, vy: 120 }; let precedent = 0; function tour(maintenant) { // dt = temps écoulé depuis le tour d'avant, en secondes const dt = precedent ? (maintenant - precedent) / 1000 : 0; precedent = maintenant; crayon.clearRect(0, 0, ecran.width, ecran.height); carre.x += carre.vx * dt; carre.y += carre.vy * dt; crayon.fillStyle = '#38bdf8'; crayon.fillRect(carre.x, carre.y, carre.taille, carre.taille); requestAnimationFrame(tour); } requestAnimationFrame(tour);
dt a un nom de métier : le delta time, le temps écoulé. Tu le retrouveras dans absolument tous les moteurs de jeu, sous le même nom. Le prendre en compte dès maintenant t'évite de devoir réécrire ton jeu plus tard, et c'est le genre de chose qui distingue un jeu qui marche d'un jeu qui marche chez toi.7. Rebondir sur les bords Ta première collision
Rebondir, c'est juste inverser la vitesse. Un carré qui allait vers la droite repart vers la gauche : sa vitesse passe de 180 à -180. Il suffit de repérer le moment où il touche un bord.
À placer juste après le calcul de la position
// Bord gauche et bord droit if (carre.x < 0) { carre.x = 0; carre.vx = -carre.vx; } if (carre.x + carre.taille > ecran.width) { carre.x = ecran.width - carre.taille; carre.vx = -carre.vx; } // Bord haut et bord bas if (carre.y < 0) { carre.y = 0; carre.vy = -carre.vy; } if (carre.y + carre.taille > ecran.height) { carre.y = ecran.height - carre.taille; carre.vy = -carre.vy; }
Recharge : ton carré rebondit indéfiniment. Tu viens de fabriquer la démo du haut de cette page.
! La ligne qu'on oublie, et le bug qu'elle évite
Regarde bien : à chaque rebond, on fait deux choses. On inverse la vitesse, et on replace le carré exactement sur le bord.
Si tu enlèves la ligne qui replace, voilà ce qui arrive : un tour où le carré dépasse un peu, on inverse la vitesse, mais au tour suivant il est encore dehors, donc on inverse encore. Le carré se met à vibrer sur le bord sans pouvoir repartir, coincé.
Enlève-la exprès pour voir. C'est un bug classique, tu le reconnaîtras toute ta vie, et savoir le provoquer vaut mieux que le lire.
Pourquoi x + taille et pas juste x
Parce que x désigne le coin haut gauche du carré. Son bord droit se trouve donc à x + taille. Si tu testais seulement x > largeur, le carré sortirait entièrement de l'écran avant de rebondir.
Cette histoire de « quel point représente l'objet » revient dans tout le développement de jeu. Certains moteurs prennent le centre, d'autres le coin. Ni l'un ni l'autre n'est mieux, il faut juste savoir lequel tu utilises.
8. Casse-le exprès Six expériences, et ce qu'elles t'apprennent
Le meilleur moyen de comprendre un programme est de le casser volontairement pendant qu'on n'a rien à perdre. Fais les six, dans l'ordre.
| Change ça | Ce qui se passe | Ce que ça t'apprend |
|---|---|---|
Enlève la ligne clearRect |
Le carré laisse une traînée derrière lui. | Le navigateur n'efface rien tout seul. C'est la case « laisser une trace » de la démo. |
Mets vx: 4000 |
Le carré traverse les murs et se perd. | En un tour, il saute par-dessus le mur sans jamais être dedans. C'est le tunneling, et ça hante tous les jeux. |
Mets vx: 0 et vy: 0 |
Il ne bouge plus, mais la boucle tourne toujours. | Un jeu qui ne bouge pas n'est pas un jeu arrêté. |
Enlève requestAnimationFrame(tour) à la fin |
Une seule image, puis plus rien. | C'est cette ligne qui relance la boucle. Sans elle, un tour et c'est fini. |
Écris carre.X au lieu de carre.x |
Le carré disparaît. | La majuscule compte. Ouvre la console du navigateur avec F12 : elle te dit ce qui ne va pas. |
| Ajoute un deuxième carré avec sa propre vitesse | Deux carrés indépendants rebondissent. | Rien ne limite le nombre d'objets. C'est comme ça qu'on fera les ennemis à l'épisode 8. |
9. Ta brique n°1 Garde-la, tu vas t'en resservir
Cette série fonctionne par briques. Chaque épisode t'en donne une, et les briques s'empilent : à la fin, elles forment un jeu complet. Range ton fichier dans un dossier mon-jeu et ne le jette pas.
1 Ce que tu sais faire maintenant
- Créer une page avec une zone de dessin
- Dessiner un rectangle où tu veux, de la taille et de la couleur que tu veux
- Faire tourner une boucle de jeu qui efface, calcule et redessine
- Déplacer un objet à une vitesse identique sur toutes les machines
- Détecter le contact avec un bord et rebondir dessus
- Lire un message d'erreur au lieu de le subir
C'est le socle de tous les jeux 2D. Un jeu de plateforme, un casse-briques et un jeu de course partagent exactement ces six choses.
2 La suite de la série
- Prends les commandes : clavier, et tactile pour jouer sur téléphone.
- Ça cogne : les collisions entre deux objets, et ton premier vrai jeu jouable.
- Le monde : une carte faite de cases, des plateformes, un décor.
- La gravité et le saut : le réglage qui rend un jeu agréable ou pénible.
- Les ennemis et la vie : les états, les dégâts, l'invincibilité qui clignote.
- Le son : fabriqué par le code, sans télécharger un seul fichier.
- L'écran de jeu : score, menu, pause, game over.
- La sauvegarde : garder le meilleur score.
- Publier : mettre ton jeu en ligne pour que tes copains y jouent.
- Passer en 3D : le même jeu, en volume.
! Un conseil avant de passer à la suite
Ne fonce pas à l'épisode suivant. Passe une demi-heure à jouer avec celui-ci : mets dix carrés, donne-leur des couleurs au hasard, fais-les partir dans tous les sens, ralentis-en un et accélère un autre.
Ce temps-là n'est pas perdu, c'est même le seul qui compte vraiment. Lire du code n'apprend rien. En casser, si.
Les cinq choses à retenir de cet épisode
- Un jeu ne bouge pas : il efface, calcule et redessine, soixante fois par seconde.
yaugmente vers le bas. Descendre, c'est augmentery.- Une vitesse se compte en pixels par seconde, jamais par image.
- Rebondir, c'est inverser la vitesse et replacer l'objet sur le bord.
- Un écran noir n'est pas un mystère : c'est un message dans la console.
Mémo publié par NET&PRO à titre pédagogique. Information générale, sans garantie d'exactitude, d'exhaustivité ni d'actualité, et sans valeur de conseil personnalisé. Avertissement et limites d'usage
Mémos liés
Three.js de A à Z
La 3D dans le navigateur : le pipeline GPU expliqué, trois démos à bidouiller.
Lire le mémoLe Frontend & UI/UX de A à Z
HTML, CSS, JS, frameworks, npm, API, design systems, accessibilité et tendances 2026 : du newbie à l'expert.
Lire le mémoAccessibilité web : par où commencer quand on part de zéro
Qui est vraiment concerné par la loi depuis juin 2025, les sept défauts que n'importe quel outil détecte en trente secondes, pourquoi les surcouches vendues comme solution n'en sont pas, et les trois tests à faire soi-même sans rien installer.
Lire le mémoSur le blog
Si vous préférez me le confier
Sur ce sujet, voici ce que je fais pour mes clients. Les formules disent ce qui est compris, ce qui ne l'est pas, et ce que ça coûte au bout de trois ans.
Un mot vous échappe ? Le glossaire le définit en une phrase, puis en détail.