├── 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 | 
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 |
--------------------------------------------------------------------------------