├── demo ├── demo.gif └── snakegame.png ├── index.html ├── LISENCE.txt ├── README.md ├── documentation └── documentation_technique.md └── script.js /demo/demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NOMO-Gabriel/Snake-Game-In-Javascript/HEAD/demo/demo.gif -------------------------------------------------------------------------------- /demo/snakegame.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NOMO-Gabriel/Snake-Game-In-Javascript/HEAD/demo/snakegame.png -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | SNAKE GAME v2 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /LISENCE.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) [2024] [NOMO-Gabriel] 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Jeu du Serpent 2 | 3 | Bienvenue dans le projet de jeu du serpent ! Ce projet implémente un jeu du serpent classique en JavaScript sur une page web. 4 | 5 | ## Table des matières 6 | 7 | - [Aperçu](#aperçu) 8 | - [Demo](#Demo) 9 | - [Test en ligne](#test-en-ligne) 10 | - [Fonctionnalités](#fonctionnalités) 11 | - [Comment jouer](#comment-jouer) 12 | - [Installation](#installation) 13 | - [Utilisation](#utilisation) 14 | - [Contribuer](#contribuer) 15 | - [Licence](#licence) 16 | 17 | ## Aperçu 18 | 19 | Le jeu du serpent est un jeu classique où vous contrôlez un serpent qui se déplace dans une grille pour manger des pommes. Chaque pomme mangée fait grandir le serpent. Le jeu se termine lorsque le serpent entre en collision avec le bord de la grille ou avec son propre corps. 20 | ![Capture video du jeu](/demo/snakegame.png) 21 | ## Démonstration du jeu 22 | [Voir la vidéo de démonstration](/demo/demo.gif) 23 | 24 | ## Tester en ligne 25 | Vous pouvez directement tester le projet en ligne sur le lien: 26 | [venez tester en ligne ici]( https://nomo-gabriel.github.io/Snake-Game-In-Javascript/) 27 | 28 | ## Fonctionnalités 29 | 30 | - Contrôles intuitifs à l'aide des touches fléchées du clavier. 31 | - Le serpent grandit lorsqu'il mange une pomme. 32 | - Le jeu se termine en cas de collision avec les murs ou le corps du serpent. 33 | - Affichage du score courant. 34 | - Possibilité de redémarrer le jeu avec la touche espace. 35 | 36 | 37 | 38 | ## Comment jouer 39 | 40 | - Utilisez les touches fléchées pour diriger le serpent dans la grille. 41 | - Mangez les pommes pour augmenter la taille du serpent et le score. 42 | - Évitez les collisions avec les murs et le corps du serpent. 43 | - Appuyez sur la touche espace pour redémarrer le jeu. 44 | 45 | ## Installation 46 | 47 | Aucune installation n'est nécessaire. Vous pouvez simplement ouvrir le fichier `index.html` dans un navigateur web pour commencer à jouer. 48 | 49 | ## Utilisation 50 | 51 | 1. Clonez ou téléchargez ce projet sur votre ordinateur. 52 | 2. Ouvrez le fichier `index.html` dans un navigateur web. 53 | 3. Commencez à jouer ! 54 | 55 | ## Contribuer 56 | 57 | Les contributions à ce projet sont les bienvenues ! N'hésitez pas à soumettre des problèmes, suggestions ou améliorations via GitHub. 58 | 59 | ## Licence 60 | 61 | Ce projet est sous licence MIT. Vous pouvez consulter le fichier `LICENSE` pour plus de détails. 62 | -------------------------------------------------------------------------------- /documentation/documentation_technique.md: -------------------------------------------------------------------------------- 1 | 2 | # Snake-Game 3 | 4 | # Documentation technique 5 | 6 | Cette documentation technique fournit des informations détaillées sur la conception et la mise en œuvre du jeu du serpent. 7 | 8 | ## Structure du code 9 | 10 | - **Variables globales** : Les variables globales incluent la taille du canevas, la taille d'un bloc, le contexte de dessin (`ctx`), le délai entre chaque mouvement du serpent (`delay`), les instances du serpent (`snakee`) et de la pomme (`applee`), et le score du joueur. 11 | 12 | - **Fonction `init()`** : Cette fonction est appelée au chargement de la fenêtre (`window.onload`) pour initialiser le jeu. Elle crée le canevas, récupère le contexte de dessin, initialise le serpent et la pomme, et lance la boucle de rafraîchissement. 13 | 14 | - **Fonction `refreshCanvas()`** : Cette fonction est appelée de manière récursive pour rafraîchir le jeu. Elle fait avancer le serpent, vérifie les collisions, efface le canevas, dessine le score, le serpent et la pomme, puis attend un délai (`delay`) avant de se rappeler elle-même. 15 | 16 | - **Fonction `gameOver()`** : Cette fonction est appelée lorsque le jeu se termine en raison d'une collision. Elle affiche un message de fin de jeu au centre du canevas. 17 | 18 | - **Fonction `restart()`** : Cette fonction réinitialise le jeu en recréant le serpent et la pomme, puis relance la boucle de rafraîchissement (`refreshCanvas`). 19 | 20 | - **Fonction `drawScore()`** : Cette fonction dessine le score courant au centre du canevas. 21 | 22 | - **Classe `Snake`** : Cette classe représente le serpent dans le jeu. Elle inclut des méthodes pour dessiner le serpent (`draw`), le faire avancer (`advance`), changer sa direction (`setDirection`), vérifier les collisions (`checkCollision`), et gérer l'action de manger une pomme (`isEatingApple`). 23 | 24 | - **Classe `Apple`** : Cette classe représente la pomme dans le jeu. Elle inclut des méthodes pour dessiner la pomme (`draw`), repositionner la pomme à une nouvelle position aléatoire (`setNewPosition`), vérifier si la pomme est sur le serpent (`isOnSnake`), et générer une couleur aléatoire pour la pomme (`generateAppleColor`). 25 | 26 | ## Gestion des événements clavier 27 | 28 | Le jeu utilise la fonction `handleKeyDown` pour gérer les événements de clavier. Les touches fléchées permettent de changer la direction du serpent, et la touche espace redémarre le jeu. 29 | 30 | --- 31 | 32 | # documentation-Technique 33 | -------------------------------------------------------------------------------- /script.js: -------------------------------------------------------------------------------- 1 | // Définition des variables globales 2 | var canvasWidth = 900; // Largeur du canevas en pixels 3 | var canvasHeight = 600; // Hauteur du canevas en pixels 4 | var blockSize = 30; // Taille d'un bloc dans le jeu 5 | var ctx; // Contexte de dessin du canevas 6 | var delay = 80; // Délai entre chaque mouvement du serpent 7 | var snakee; // Instance du serpent 8 | var applee; // Instance de la pomme 9 | var widthInblocks = canvasWidth / blockSize; // Largeur du canevas en blocs 10 | var heightInblocks = canvasHeight / blockSize; // Hauteur du canevas en blocs 11 | var score = 0; // Score du joueur 12 | var timeOut; // Gestionnaire de temps pour rafraîchir le jeu 13 | 14 | // Fonction exécutée au chargement de la fenêtre 15 | window.onload = function () { 16 | init(); 17 | } 18 | 19 | // Initialisation du jeu 20 | function init() { 21 | // Création du canevas 22 | var canvas = document.createElement("canvas"); 23 | canvas.width = canvasWidth; 24 | canvas.height = canvasHeight; 25 | canvas.style.border = "50px solid darkblue"; 26 | canvas.style.margin = "50px auto"; 27 | canvas.style.display = "block"; 28 | canvas.style.backgroundColor = "#ddd"; 29 | document.body.appendChild(canvas); 30 | 31 | // Récupération du contexte de dessin 32 | ctx = canvas.getContext('2d'); 33 | 34 | // Création du serpent 35 | snakee = new Snake([[6, 4], [5, 4], [4, 4]], "right"); 36 | applee = new Apple([7, 9]); 37 | 38 | // Lancement du jeu 39 | refreshCanvas(); 40 | } 41 | 42 | // Rafraîchissement du canevas 43 | function refreshCanvas() { 44 | // Faire avancer le serpent 45 | snakee.advance(); 46 | 47 | // Vérifier si le serpent a eu un accident 48 | if (snakee.checkCollision()) { 49 | gameOver(); 50 | } else { 51 | // Vérifier si le serpent mange une pomme 52 | if (snakee.isEatingApple(applee)) { 53 | score++; 54 | snakee.ateApple = true; 55 | 56 | // Déplacer la pomme à une nouvelle position 57 | do { 58 | applee.setNewPosition(); 59 | } while (applee.isOnSnake(snakee)); 60 | } 61 | 62 | // Effacer le canevas entier 63 | ctx.clearRect(0, 0, canvasWidth, canvasHeight); 64 | 65 | // Dessiner le score 66 | drawScore(); 67 | 68 | // Dessiner le serpent 69 | snakee.draw(); 70 | 71 | // Dessiner la pomme 72 | applee.draw(); 73 | 74 | // Appel récursif avec un délai 75 | timeOut = setTimeout(refreshCanvas, delay); 76 | } 77 | } 78 | 79 | // Fonction de fin de jeu 80 | function gameOver() { 81 | var centerX = canvasWidth / 2; 82 | var centerY = canvasHeight / 2; 83 | ctx.save(); 84 | ctx.font = "bold 50px sans-serif"; 85 | ctx.textAlign = "center"; 86 | ctx.fillStyle = "red"; 87 | ctx.strokeStyle = "white"; 88 | ctx.lineWidth = 10; 89 | ctx.textBaseline = "middle"; 90 | ctx.strokeText("Game Over", centerX, centerY - 180); 91 | ctx.fillText("Game Over", centerX, centerY - 180); 92 | ctx.font = "bold 30px sans-serif"; 93 | ctx.strokeText("Appuyer sur Espace pour Rejouer", centerX, centerY - 120); 94 | ctx.fillText("Appuyer sur Espace pour Rejouer", centerX, centerY - 120); 95 | ctx.restore(); 96 | } 97 | 98 | // Fonction pour redémarrer le jeu 99 | function restart() { 100 | score = 0; // Réinitialisation du score 101 | 102 | // Recréer le serpent et la pomme 103 | snakee = new Snake([[6, 4], [5, 4], [4, 4]], "right"); 104 | applee = new Apple([7, 9]); 105 | 106 | // Annuler le timeout précédent et relancer le jeu 107 | clearTimeout(timeOut); 108 | refreshCanvas(); 109 | } 110 | 111 | // Fonction pour dessiner le score sur le canevas 112 | function drawScore() { 113 | var centerX = canvasWidth / 2; 114 | var centerY = canvasHeight / 2; 115 | var text = "Score : " + score.toString(); 116 | 117 | ctx.save(); 118 | ctx.font = "bold 100px sans-serif"; 119 | ctx.textAlign = "center"; 120 | ctx.textBaseline = "middle"; 121 | ctx.strokeStyle = "darkblue"; 122 | ctx.lineWidth = 7; 123 | ctx.strokeText(text, centerX, centerY); 124 | ctx.fillStyle = "white"; 125 | ctx.fillText(text, centerX, centerY); 126 | ctx.restore(); 127 | } 128 | 129 | // Fonction pour dessiner un bloc 130 | function drawBlock(ctx, position) { 131 | var x = position[0] * blockSize; 132 | var y = position[1] * blockSize; 133 | ctx.fillRect(x, y, blockSize, blockSize); 134 | } 135 | 136 | // Classe Snake (serpent) 137 | function Snake(body, direction) { 138 | this.body = body; // Corps du serpent (tableau de positions) 139 | this.direction = direction; // Direction actuelle du serpent 140 | this.ateApple = false; // Indicateur pour savoir si le serpent a mangé une pomme 141 | 142 | // Méthode pour dessiner le serpent 143 | this.draw = function () { 144 | ctx.save(); 145 | ctx.fillStyle = "blue"; 146 | 147 | // Dessiner chaque partie du serpent 148 | for (var i = 0; i < this.body.length; i++) { 149 | drawBlock(ctx, this.body[i]); 150 | } 151 | ctx.restore(); 152 | }; 153 | 154 | // Méthode pour faire avancer le serpent 155 | this.advance = function () { 156 | var nextPosition = this.body[0].slice(); 157 | switch (this.direction) { 158 | case "right": 159 | nextPosition[0]++; 160 | break; 161 | case "left": 162 | nextPosition[0]--; 163 | break; 164 | case "down": 165 | nextPosition[1]++; 166 | break; 167 | case "up": 168 | nextPosition[1]--; 169 | break; 170 | default: 171 | throw new Error("Direction invalide"); 172 | } 173 | 174 | // Ajouter la nouvelle position au début du tableau 175 | this.body.unshift(nextPosition); 176 | 177 | // Si le serpent n'a pas mangé de pomme, retirer la dernière position 178 | if (!this.ateApple) { 179 | this.body.pop(); 180 | } else { 181 | this.ateApple = false; 182 | } 183 | }; 184 | 185 | // Méthode pour changer la direction du serpent 186 | this.setDirection = function (newDirection) { 187 | var allowedDirections; 188 | switch (this.direction) { 189 | case "right": 190 | case "left": 191 | allowedDirections = ["up", "down"]; 192 | break; 193 | case "down": 194 | case "up": 195 | allowedDirections = ["left", "right"]; 196 | break; 197 | default: 198 | throw new Error("Direction invalide"); 199 | } 200 | // Si la nouvelle direction est autorisée, mettez-la à jour 201 | if (allowedDirections.includes(newDirection)) { 202 | this.direction = newDirection; 203 | } 204 | }; 205 | 206 | // Méthode pour vérifier les collisions 207 | this.checkCollision = function () { 208 | var wallCollision = false; 209 | var snakeCollision = false; 210 | 211 | // Position de la tête du serpent 212 | var head = this.body[0]; 213 | var rest = this.body.slice(1); 214 | var snakeX = head[0]; 215 | var snakeY = head[1]; 216 | var minX = 0; 217 | var minY = 0; 218 | var maxX = widthInblocks - 1; 219 | var maxY = heightInblocks - 1; 220 | 221 | // Vérifier la collision avec les murs 222 | var isHorizontalCollision = snakeX < minX || snakeX > maxX; 223 | var isVerticalCollision = snakeY < minY || snakeY > maxY; 224 | if (isHorizontalCollision || isVerticalCollision) { 225 | wallCollision = true; 226 | } 227 | 228 | // Vérifier la collision avec le corps du serpent 229 | for (var i = 0; i < rest.length; i++) { 230 | if (snakeX === rest[i][0] && snakeY === rest[i][1]) { 231 | snakeCollision = true; 232 | break; 233 | } 234 | } 235 | 236 | return wallCollision || snakeCollision; 237 | }; 238 | 239 | // Vérifier si le serpent mange une pomme 240 | this.isEatingApple = function (appleToEat) { 241 | var head = this.body[0]; 242 | return head[0] === appleToEat.position[0] && head[1] === appleToEat.position[1]; 243 | }; 244 | } 245 | 246 | // Classe Apple (pomme) 247 | function Apple(position) { 248 | this.position = position; // Position de la pomme 249 | this.color = "red"; // Couleur de la pomme 250 | 251 | // Dessiner la pomme sur le canevas 252 | this.draw = function () { 253 | ctx.save(); 254 | ctx.fillStyle = this.color; 255 | ctx.beginPath(); 256 | var radius = blockSize / 2; 257 | var x = this.position[0] * blockSize + radius; 258 | var y = this.position[1] * blockSize + radius; 259 | 260 | // Dessiner un cercle 261 | ctx.arc(x, y, radius, 0, Math.PI * 2); 262 | ctx.fill(); 263 | ctx.restore(); 264 | }; 265 | 266 | // Repositionner la pomme à une nouvelle position aléatoire 267 | this.setNewPosition = function () { 268 | var newX = Math.round(Math.random() * (widthInblocks - 1)); 269 | var newY = Math.round(Math.random() * (heightInblocks - 1)); 270 | this.position = [newX, newY]; 271 | this.generateAppleColor(); 272 | }; 273 | 274 | // Vérifier si la pomme est sur le serpent 275 | this.isOnSnake = function (snakeToCheck) { 276 | var isOnSnake = false; 277 | for (var i = 0; i < snakeToCheck.body.length; i++) { 278 | if (this.position[0] === snakeToCheck.body[i][0] && this.position[1] === snakeToCheck.body[i][1]) { 279 | isOnSnake = true; 280 | break; 281 | } 282 | } 283 | return isOnSnake; 284 | }; 285 | 286 | // Générer une couleur aléatoire pour la pomme 287 | this.generateAppleColor = function () { 288 | var colors = ["red", "green", "yellow", "blue", "pink", "violet", "black"]; 289 | var selectedIndex = Math.floor(Math.random() * colors.length); 290 | var selectedColor = colors[selectedIndex]; 291 | this.color = selectedColor; 292 | }; 293 | } 294 | 295 | // Gestion des événements clavier 296 | document.onkeydown = function handleKeyDown(e) { 297 | var newDirection; 298 | switch (e.key) { 299 | case "ArrowLeft": 300 | newDirection = "left"; 301 | break; 302 | case "ArrowUp": 303 | newDirection = "up"; 304 | break; 305 | case "ArrowRight": 306 | newDirection = "right"; 307 | break; 308 | case "ArrowDown": 309 | newDirection = "down"; 310 | break; 311 | case " ": 312 | restart(); 313 | return; 314 | default: 315 | return; 316 | } 317 | snakee.setDirection(newDirection); 318 | } 319 | --------------------------------------------------------------------------------