Hostinger

Comment créer un jeu Snake en HTML, CSS et JavaScript

Vidéo sur Youtube Le play Youtube

Bienvenue 🤗 !

Nous allons créer un jeu très populaire des années 2000 : le célèbre "Snake" que l’on retrouvait sur les Nokia 3210 et 3310.

Nous allons coder ce jeu en HTML, CSS et JavaScript.

Les personnes actuellement dans la quarantaine y ont beaucoup joué.

Mise en place du projet pour créer le jeu Snake

Nous devons créer trois fichiers dans un dossier.

project_game_snake
|-- index.php
|-- style.css
|-- script.js

Remplissez le fichier index.php

C’est le fichier le plus facile à compléter. Nous allons partir d’une structure de base, utiliser une balise <canvas> pour dessiner jeu et ajouter du code permettant d’importer le fichier CSS ainsi que le fichier script.js.

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8" />
  <title>Jeu Snake - Nokia 3310</title>
  <link rel="stylesheet" href="style.css" />
</head>
<body>
  <h1>Jeu Snake (Nokia 3310)</h1>
  <canvas id="gameCanvas" width="400" height="400"></canvas>
  <p id="score">Score : 0</p>
  <script src="script.js"></script>
</body>
</html>

Serveur local

Pour déployer notre jeu, j’utiliserai un serveur PHP.

C’est justement pour cette raison que j’ai nommé mon fichier `index.php`.

Bien sûr, si vous le souhaitez, vous pouvez utiliser une autre méthode.

Vérifier PHP

Pour vérifier que PHP est correctement installé, ouvrez un terminal et exécutez la commande suivante.

php -v

Si PHP est installé, vous verrez s’afficher un numéro de version.

PHP 8.3.13 (cli)

Sinon, vous devrez installer PHP si vous souhaitez l’utiliser.

Lancer le serveur

Pour démarrer le serveur PHP, ouvrez votre terminal, naviguez jusqu’au dossier contenant vos trois fichiers et exécutez la commande suivante.

php -S "localhost:7777"

Le jeu sera accessible à l’adresse localhost:7777.

Si le port 7777 est déjà utilisé, choisissez un autre port.

Lancer le jeu

Ouvrez un navigateur et dans la barre d'adresse tapez : localhost:7777.

Voici le résultat pour le moment.

Créer le jeu Snake : étape 1

Remplissez le fichier style.css

Nous allons maintenant rédiger le contenu du fichier de style.

body {
    margin: 0;
    padding: 0;
    background: #222;
    font-family: Arial, sans-serif;
    color: #fff;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: flex-start;
    height: 100vh;
  }
  
  h1 {
    margin-top: 20px;
    margin-bottom: 10px;
  }
  
  #gameCanvas {
    background: #333;
    border: 2px solid #fff;
    display: block;
    margin: 0 auto;
    margin-bottom: 10px;
  }
  
  #score {
    font-size: 1.2rem;
    margin-bottom: 20px;
  }

Nous avons modifié l'affichage de la balise <body>, styliser l’écran du jeu et effectuer d’autres ajustements esthétiques.

Résultat

En ouvrant un navigateur et en accédant à localhost:7777, vous pourrez voir le résultat avec le style.

Créer le jeu Snake : étape 2

Remplissez le fichier script.js

Le fichier script.js est le plus important, car c’est grâce au JavaScript que nous allons véritablement créer le jeu.

Bien que cela soit un peu plus complexe, c’est tout à fait réalisable.

Pour vous accompagner étape par étape, je vais détailler le code.

1 - Les variable à utiliser

Nous allons débuter en définissant certaines variables essentielles.

// Récupérer le canvas et son contexte 2D
const canvas = document.getElementById("gameCanvas");
const ctx = canvas.getContext("2d");

// Dimensions du canvas
const width = canvas.width;
const height = canvas.height;

// Taille d'une case (chaque segment du serpent et la nourriture font 20px)
const boxSize = 20;

// Vitesse du jeu en millisecondes (100 ms = 10 mises à jour par seconde)
const gameSpeed = 100;

// Le serpent : un tableau d'objets { x, y }
// On initialise le serpent avec un seul segment (la tête)
let snake = [
  { x: 9 * boxSize, y: 10 * boxSize } // Position de départ au milieu du canvas
];

// Direction initiale du serpent
let direction = "RIGHT";

// Score initial
let score = 0;

// Sélection de l'élément HTML pour afficher le score
const scoreDisplay = document.getElementById("score");

// Cette variable contiendra l'intervalle qui appelle régulièrement la fonction du jeu
let game;

2 - Créer la fonction pour dessiner un carré

Pour dessiner le serpent et la nourriture sur le canvas, il faut définir une fonction.

/**
 * Dessine un carré de taille boxSize sur le canvas
 * @param {number} x - Coordonnée x
 * @param {number} y - Coordonnée y
 * @param {string} color - Couleur de remplissage
 */
function drawBox(x, y, color) {
  ctx.fillStyle = color;
  ctx.fillRect(x, y, boxSize, boxSize);
}

3 - Générer la génération de nourriture aléatoirement

Le serpent doit se nourrir en mangeant des aliments représentés par un carré, qui apparaissent à des emplacements aléatoires.

/**
 * Génère une position aléatoire pour la nourriture
 * @returns {Object} { x, y }
 */
function spawnFood() {
  return {
    x: Math.floor(Math.random() * (width / boxSize)) * boxSize,
    y: Math.floor(Math.random() * (height / boxSize)) * boxSize,
  };
}
// Génération d’une première nourriture
let food = spawnFood();

4 - Détecter les touches du clavier et changer la direction du serpent

On souhaite que le serpent change de direction quand on appuie sur les touches fléchées (↑, ↓, ←, →). Pour ça, on écoute l’événement keydown et on met à jour notre variable direction.

// Écoute des touches du clavier
document.addEventListener("keydown", changeDirection);
/**
 * Change la direction en fonction de la touche appuyée
 * @param {KeyboardEvent} e
 */
function changeDirection(e) {
  if (e.key === "ArrowLeft" && direction !== "RIGHT") {
    direction = "LEFT";
  } else if (e.key === "ArrowUp" && direction !== "DOWN") {
    direction = "UP";
  } else if (e.key === "ArrowRight" && direction !== "LEFT") {
    direction = "RIGHT";
  } else if (e.key === "ArrowDown" && direction !== "UP") {
    direction = "DOWN";
  }
}

5 - Vérifier la collision du serpent avec son corps

Pour vérifier si le serpent se mord lui-même, on compare la position de la nouvelle tête avec chacune des cases de son corps. Si les coordonnées sont identiques, c’est une collision.

/**
 * Vérifie si la tête du serpent (head) entre en collision
 * avec un segment du corps (body).
 * @param {Object} head - La nouvelle tête { x, y }
 * @param {Array} body - Les segments du serpent
 * @returns {boolean} true si collision, false sinon
 */
function collisionWithBody(head, body) {
  for (let i = 0; i < body.length; i++) {
    if (head.x === body[i].x && head.y === body[i].y) {
      return true;
    }
  }
  return false;
}

6 - Écrire la fonction principale drawGame()

Il s’agit de la fonction principale du jeu, appelée de manière récurrente.

Le rôle de cette fonction essentielle

  1. Effacer le canvas.
  2. Dessiner la nourriture.
  3. Mettre à jour les coordonnées du serpent (calcul de la nouvelle tête).
  4. Vérifier si le serpent mange la nourriture (score + création d’une nouvelle nourriture).
  5. Retirer la queue du serpent si pas de nourriture mangée.
  6. Vérifier les collisions (murs et corps).
  7. Dessiner chaque segment du serpent.

La fonction drawGame()

/**
 * Fonction principale qui dessine et met à jour l'état du jeu
 */
function drawGame() {
  // 1. Efface le canvas (toute la zone de dessin)
  ctx.clearRect(0, 0, width, height);

  // 2. Dessiner la nourriture
  drawBox(food.x, food.y, "red");

  // 3. Coordonnées de la tête du serpent (segment 0)
  let snakeX = snake[0].x;
  let snakeY = snake[0].y;

  // Mise à jour de la position selon la direction
  if (direction === "LEFT")  snakeX -= boxSize;
  if (direction === "RIGHT") snakeX += boxSize;
  if (direction === "UP")    snakeY -= boxSize;
  if (direction === "DOWN")  snakeY += boxSize;

  // 4. Vérifier si le serpent mange la nourriture
  if (snakeX === food.x && snakeY === food.y) {
    // Incrémente le score
    score++;
    scoreDisplay.textContent = `Score : ${score}`;

    // Génère une nouvelle nourriture
    food = spawnFood();

    // Le serpent grandit => on ne retire pas le dernier segment
  } else {
    // 5. On enlève le dernier segment (la queue) pour simuler le mouvement
    snake.pop();
  }

  // Préparer la nouvelle tête
  let newHead = { x: snakeX, y: snakeY };

  // 6a. Collision avec les murs ?
  if (
    snakeX < 0 ||
    snakeX >= width ||
    snakeY < 0 ||
    snakeY >= height
  ) {
    // Fin du jeu
    clearInterval(game);
    alert(`Game Over ! Votre score est de : ${score}`);
    return;
  }

  // 6b. Collision avec le corps ?
  if (collisionWithBody(newHead, snake)) {
    // Fin du jeu
    clearInterval(game);
    alert(`Game Over ! Votre score est de : ${score}`);
    return;
  }

  // On ajoute la nouvelle tête au début du tableau
  snake.unshift(newHead);

  // 7. Dessiner le serpent
  for (let i = 0; i < snake.length; i++) {
    // La tête est plus claire (lime), le reste est vert
    drawBox(snake[i].x, snake[i].y, i === 0 ? "lime" : "green");
  }
}

7 - Démarrer la boucle de jeu

Il ne reste plus qu’à appeler la fonction drawGame() toutes les gameSpeed millisecondes. C’est ce qui va faire « tourner » le jeu en continu.

// Lance la boucle du jeu
game = setInterval(drawGame, gameSpeed);

Lancer le jeu Snake de Nokia 3310

Actualisez votre navigateur web (comme Google Chrome, par exemple). Le jeu devrait s’afficher.

Félicitation pour votre travail. 👍