Créer un jeu de serpent avec javascript

serpent

Snake est un jeu classique auquel des millions de personnes ont joué. Avez-vous déjà pensé à créer votre propre Snake Game ? Créer un jeu de serpent en utilisant HTML, CSS et JavaScript vanille est un projet amusant et éducatif qui peut améliorer vos compétences en développement Web.
Dans cet article de blog, je vais vous guider à travers les étapes de création de votre propre jeu de serpent à partir de zéro. Vous pouvez jouer à ce jeu sur un PC à l'aide des touches fléchées du clavier ou sur un appareil mobile à l'aide des touches fléchées tactiles.

Faire un jeu de serpent n'est pas seulement amusant, mais cela peut également vous aider à développer des compétences en résolution de problèmes et la capacité de décomposer des problèmes complexes en plus petits.

Codes Sources

Code HTML

Pour commencer, ajoutez les codes HTML suivants à votre fichier index.html pour créer la mise en page de base du jeu. Le conteneur "play-board" est vide maintenant, mais il sera rempli de corps de serpent et d'éléments alimentaires plus tard en utilisant du code JavaScript
 
   <div class="wrapper"> 
      <div class="game-details"> 
        <span class="score">Score: 0</span> 
        <span class="high-score">Meilleur score: 0</span> 
      </div> 
      <div class="play-board"></div> 
      <div class="controls"> 
        <i data-key="ArrowLeft" class="fa-solid fa-arrow-left-long"></i> 
        <i data-key="ArrowUp" class="fa-solid fa-arrow-up-long"></i> 
        <i data-key="ArrowRight" class="fa-solid fa-arrow-right-long"></i> 
        <i data-key="ArrowDown" class="fa-solid fa-arrow-down-long"></i> 
      </div> 
    </div> 

Code CSS

Ensuite, ajoutez les codes CSS suivants à votre fichier style.css pour créer la mise en page du jeu Snake. N'oubliez pas que les touches fléchées de contrôle ne sont affichées que sur les petits appareils, tels que les téléphones. Si vous préférez les afficher sur tous les appareils, vous pouvez facilement modifier le code de requête multimédia.
 
    /*Google font */ @import url('https://fonts.googleapis.com/css2?family=Open+Sans:[email protected];500;600;700&display=swap'); 
* { 
  margin: 0; 
  padding: 0; 
  box-sizing: border-box; 
  font-family: 'Open Sans', sans-serif; 
} 
body { 
  display: flex; 
  align-items: center; 
  justify-content: center; 
  min-height: 100vh; 
  background: #E3F2FD; 
} 
.wrapper { 
  width: 65vmin; 
  height: 70vmin; 
  display: flex; 
  overflow: hidden; 
  flex-direction: column; 
  justify-content: center; 
  border-radius: 5px; 
  background: #293447; 
  box-shadow: 0 20px 40px rgba(52, 87, 220, 0.2); 
} 
.game-details { 
  color: #B8C6DC; 
  font-weight: 500; 
  font-size: 1.2rem; 
  padding: 20px 27px; 
  display: flex; 
  justify-content: space-between; 
} 
.play-board { 
  height: 100%; 
  width: 100%; 
  display: grid; 
  background: #212837; 
  grid-template: repeat(30, 1fr) / repeat(30, 1fr); 
} 
.play-board .food { 
  background: #FF003D; 
} 
.play-board .head { 
  background: #60CBFF; 
} 
 
.controls { 
  display: none; 
  justify-content: space-between; 
} 
.controls i { 
  padding: 25px 0; 
  text-align: center; 
  font-size: 1.3rem; 
  color: #B8C6DC; 
  width: calc(100% / 4); 
  cursor: pointer; 
  border-right: 1px solid #171B26; 
} 
 
@media screen and (max-width: 800px) { 
  .wrapper { 
    width: 90vmin; 
    height: 115vmin; 
  } 
  .game-details { 
    font-size: 1rem; 
    padding: 15px 27px; 
  } 
  .controls { 
    display: flex; 
  } 
  .controls i { 
    padding: 15px 0; 
    font-size: 1rem; 
  } 
}

Code JavaScript

Enfin, ajoutez le code JavaScript suivant à votre fichier script.js pour ajouter des fonctionnalités pour le jeu du serpent. Ce code gérera la logique derrière le mouvement du serpent, manger de la nourriture, mettre à jour le score et détecter les collisions avec les murs ou son propre corps
 
   const playBoard = document.querySelector(".play-board"); 
const scoreElement = document.querySelector(".score"); 
const highScoreElement = document.querySelector(".high-score"); 
const controls = document.querySelectorAll(".controls i"); 
 
let gameOver = false; 
let foodX, foodY; 
let snakeX = 5, snakeY = 5; 
let velocityX = 0, velocityY = 0; 
let snakeBody = []; 
let setIntervalId; 
let score = 0; 
 
// Obtenir le meilleur score dans le localstorage 
let highScore = localStorage.getItem("high-score") || 0; 
highScoreElement.innerText = `Meilleure score: ${highScore}`; 
 
const updateFoodPosition = () => { 
    // Passer de 1 - 30 aléatoirement 
    foodX = Math.floor(Math.random() * 30) + 1; 
    foodY = Math.floor(Math.random() * 30) + 1; 
} 
 
const handleGameOver = () => { 
    // Supprimer le score actuelle et afficher le popup
    clearInterval(setIntervalId); 
    alert("GAME OVER 😭😂"); 
    location.reload(); 
} 
 
const changeDirection = e => { 
    // Les touches d'ordinateur 
    if(e.key === "ArrowUp" && velocityY != 1) { 
        velocityX = 0; 
        velocityY = -1; 
    } else if(e.key === "ArrowDown" && velocityY != -1) { 
        velocityX = 0; 
        velocityY = 1; 
    } else if(e.key === "ArrowLeft" && velocityX != 1) { 
        velocityX = -1; 
        velocityY = 0; 
    } else if(e.key === "ArrowRight" && velocityX != -1) { 
        velocityX = 1; 
        velocityY = 0; 
    } 
} 
 
// Appel de changeDirection à chaque clic de touche et transmission de la valeur de l'ensemble de données clés en tant qu'objet 
controls.forEach(button => button.addEventListener("click", () => changeDirection({ key: button.dataset.key }))); 
 
const initGame = () => { 
    if(gameOver) return handleGameOver(); 
    let html = `<div class="food" style="grid-area: ${foodY} / ${foodX}"></div>`; 
 
    // Vérifier si le serpent à mangé la nourriture 
    if(snakeX === foodX && snakeY === foodY) { 
        updateFoodPosition(); 
        snakeBody.push([foodY, foodX]); // Pousser la position de la nourriture vers le corps du serpent 
        score++; // augmenter le score de 1 
        highScore = score >= highScore ? score : highScore; 
        localStorage.setItem("high-score", highScore); 
        scoreElement.innerText = `Score: ${score}`; 
        highScoreElement.innerText = `Meilleure score: ${highScore}`; 
    } 
    // Mise à jour de la position de la tête du serpent en fonction de la vitesse actuelle 
    snakeX += velocityX; 
    snakeY += velocityY; 
     
    // Décaler d'une unité les valeurs des éléments du corps du serpent 
    for (let i = snakeBody.length - 1; i > 0; i--) { 
        snakeBody[i] = snakeBody[i - 1]; 
    } 
    snakeBody[0] = [snakeX, snakeY]; // Réglage du premier élément du corps du serpent à la position actuelle du serpent 
 
    // Vérifier si la tête du serpent est hors du mur, si c'est le cas, régler gameOver sur true 
    if(snakeX <= 0 || snakeX > 30 || snakeY <= 0 || snakeY > 30) { 
        return gameOver = true; 
    } 
 
    for (let i = 0; i < snakeBody.length; i++) { 
        // Ajout d'un div pour chaque partie du corps du serpent 
        html += `<div class="head" style="grid-area: ${snakeBody[i][1]} / ${snakeBody[i][0]}"></div>`; 
        // Vérifier si la tête de serpent a touché le corps, si c'est le cas, définissez gameOver sur true 
        if (i !== 0 && snakeBody[0][1] === snakeBody[i][1] && snakeBody[0][0] === snakeBody[i][0]) { 
            gameOver = true; 
        } 
    } 
    playBoard.innerHTML = html; 
} 
 
updateFoodPosition(); 
setIntervalId = setInterval(initGame, 100); 
document.addEventListener("keyup", changeDirection); 

Dans le code, vous pouvez voir que la vitesse actuelle du serpent est de 100 millisecondes, ce qui détermine la vitesse à laquelle le serpent se déplace sur le plateau de jeu. Vous pouvez facilement ajuster cette vitesse en modifiant la valeur dans la fonction "setInterval" en bas du code.


En suivant les étapes de cet article de blog, vous avez créé avec succès un jeu de serpent classique utilisant HTML, CSS et JavaScript auquel vous pouvez jouer sur n'importe quel navigateur d'appareil. J'espère que ce projet de jeu de serpent vous aidera à comprendre la manipulation du DOM, les compétences en résolution de problèmes et d'autres compétences en développement Web.
Si vous avez aimé créer votre jeu de serpent et appris quelque chose de nouveau, alors n'hésitez pas à commenter ou à lâcher une réaction en bas de ce post.
Ces jeux sont non seulement agréables à créer, mais offrent également une excellente occasion de pratiquer et d'améliorer vos compétences en JavaScript.
Si vous rencontrez des problèmes ou si votre code ne fonctionne pas comme prévu, vous pouvez copier le code complet disponible ci-dessous

Code complète

 
 <!DOCTYPE html>
<html lang="en" dir="ltr"> 
  <head> 
    <meta charset="utf-8"> 
    <title>Jeux Serpent</title> 
    <link rel="stylesheet" href="style.css"> 
    <meta name="viewport" content="width=device-width, initial-scale=1.0"> 
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.3.0/css/all.min.css"> 
  </head> 
  <style>
/*Google font */ @import url('https://fonts.googleapis.com/css2?family=Open+Sans:[email protected];500;600;700&display=swap'); 
* { 
  margin: 0; 
  padding: 0; 
  box-sizing: border-box; 
  font-family: 'Open Sans', sans-serif; 
} 
body { 
  display: flex; 
  align-items: center; 
  justify-content: center; 
  min-height: 100vh; 
  background: #E3F2FD; 
} 
.wrapper { 
  width: 65vmin; 
  height: 70vmin; 
  display: flex; 
  overflow: hidden; 
  flex-direction: column; 
  justify-content: center; 
  border-radius: 5px; 
  background: #293447; 
  box-shadow: 0 20px 40px rgba(52, 87, 220, 0.2); 
} 
.game-details { 
  color: #B8C6DC; 
  font-weight: 500; 
  font-size: 1.2rem; 
  padding: 20px 27px; 
  display: flex; 
  justify-content: space-between; 
} 
.play-board { 
  height: 100%; 
  width: 100%; 
  display: grid; 
  background: #212837; 
  grid-template: repeat(30, 1fr) / repeat(30, 1fr); 
} 
.play-board .food { 
  background: #FF003D; 
} 
.play-board .head { 
  background: #60CBFF; 
} 
 
.controls { 
  display: none; 
  justify-content: space-between; 
} 
.controls i { 
  padding: 25px 0; 
  text-align: center; 
  font-size: 1.3rem; 
  color: #B8C6DC; 
  width: calc(100% / 4); 
  cursor: pointer; 
  border-right: 1px solid #171B26; 
} 
 
@media screen and (max-width: 800px) { 
  .wrapper { 
    width: 90vmin; 
    height: 115vmin; 
  } 
  .game-details { 
    font-size: 1rem; 
    padding: 15px 27px; 
  } 
  .controls { 
    display: flex; 
  } 
  .controls i { 
    padding: 15px 0; 
    font-size: 1rem; 
  } 
}
  </style>
  <body> 
    <div class="wrapper"> 
      <div class="game-details"> 
        <span class="score">Score: 0</span> 
        <span class="high-score">Meilleur score: 0</span> 
      </div> 
      <div class="play-board"></div> 
      <div class="controls"> 
        <i data-key="ArrowLeft" class="fa-solid fa-arrow-left-long"></i> 
        <i data-key="ArrowUp" class="fa-solid fa-arrow-up-long"></i> 
        <i data-key="ArrowRight" class="fa-solid fa-arrow-right-long"></i> 
        <i data-key="ArrowDown" class="fa-solid fa-arrow-down-long"></i> 
      </div> 
    </div> 
 <script>
     
const playBoard = document.querySelector(".play-board"); 
const scoreElement = document.querySelector(".score"); 
const highScoreElement = document.querySelector(".high-score"); 
const controls = document.querySelectorAll(".controls i"); 
 
let gameOver = false; 
let foodX, foodY; 
let snakeX = 5, snakeY = 5; 
let velocityX = 0, velocityY = 0; 
let snakeBody = []; 
let setIntervalId; 
let score = 0; 
 
// Obtenir le meilleur score dans le localstorage 
let highScore = localStorage.getItem("high-score") || 0; 
highScoreElement.innerText = `Meilleure score: ${highScore}`; 
 
const updateFoodPosition = () => { 
    // Passer de 1 - 30 aléatoirement 
    foodX = Math.floor(Math.random() * 30) + 1; 
    foodY = Math.floor(Math.random() * 30) + 1; 
} 
 
const handleGameOver = () => { 
    // Supprimer le score actuelle et afficher le popup
    clearInterval(setIntervalId); 
    alert("GAME OVER 😭😂"); 
    location.reload(); 
} 
 
const changeDirection = e => { 
    // Les touches d'ordinateur 
    if(e.key === "ArrowUp" && velocityY != 1) { 
        velocityX = 0; 
        velocityY = -1; 
    } else if(e.key === "ArrowDown" && velocityY != -1) { 
        velocityX = 0; 
        velocityY = 1; 
    } else if(e.key === "ArrowLeft" && velocityX != 1) { 
        velocityX = -1; 
        velocityY = 0; 
    } else if(e.key === "ArrowRight" && velocityX != -1) { 
        velocityX = 1; 
        velocityY = 0; 
    } 
} 
 
// Appel de changeDirection à chaque clic de touche et transmission de la valeur de l'ensemble de données clés en tant qu'objet 
controls.forEach(button => button.addEventListener("click", () => changeDirection({ key: button.dataset.key }))); 
 
const initGame = () => { 
    if(gameOver) return handleGameOver(); 
    let html = `<div class="food" style="grid-area: ${foodY} / ${foodX}"></div>`; 
 
    // Vérifier si le serpent à mangé la nourriture 
    if(snakeX === foodX && snakeY === foodY) { 
        updateFoodPosition(); 
        snakeBody.push([foodY, foodX]); // Pousser la position de la nourriture vers le corps du serpent 
        score++; // augmenter le score de 1 
        highScore = score >= highScore ? score : highScore; 
        localStorage.setItem("high-score", highScore); 
        scoreElement.innerText = `Score: ${score}`; 
        highScoreElement.innerText = `Meilleure score: ${highScore}`; 
    } 
    // Mise à jour de la position de la tête du serpent en fonction de la vitesse actuelle 
    snakeX += velocityX; 
    snakeY += velocityY; 
     
    // Décaler d'une unité les valeurs des éléments du corps du serpent 
    for (let i = snakeBody.length - 1; i > 0; i--) { 
        snakeBody[i] = snakeBody[i - 1]; 
    } 
    snakeBody[0] = [snakeX, snakeY]; // Réglage du premier élément du corps du serpent à la position actuelle du serpent 
 
    // Vérifier si la tête du serpent est hors du mur, si c'est le cas, régler gameOver sur true 
    if(snakeX <= 0 || snakeX > 30 || snakeY <= 0 || snakeY > 30) { 
        return gameOver = true; 
    } 
 
    for (let i = 0; i < snakeBody.length; i++) { 
        // Ajout d'un div pour chaque partie du corps du serpent 
        html += `<div class="head" style="grid-area: ${snakeBody[i][1]} / ${snakeBody[i][0]}"></div>`; 
        // Vérifier si la tête de serpent a touché le corps, si c'est le cas, définissez gameOver sur true 
        if (i !== 0 && snakeBody[0][1] === snakeBody[i][1] && snakeBody[0][0] === snakeBody[i][0]) { 
            gameOver = true; 
        } 
    } 
    playBoard.innerHTML = html; 
} 
 
updateFoodPosition(); 
setIntervalId = setInterval(initGame, 100); 
document.addEventListener("keyup", changeDirection);
 </script>
  </body> 
</html>   
  • A+
  • A-