Bonjour les devs,

Je m'entraîne sur JavaScript en réalisation un jeu Snake avec Canvas.

J'ai bien avancé : on peut manipuler la direction du serpent à l'aide des touches directionnelles ; la pomme est initialisée à une position donnée dans le Canvas ; les collisions sur les murs et sur le corps du serpent sont gérées ; le serpent devrait pouvoir manger la pomme - et la pomme apparaît donc à une nouvelle position.

Jusque là c'est OK. La pomme apparaît à une nouvelle position quand le serpent la mange. Néanmoins, l'ancienne pomme est toujours visible sur la carte bien qu'elle n'existe plus à cette position. Je m'explique : lorsqu'on passe sur l'ancienne pomme, rien ne se passe - dès qu'on passe sur la nouvelle, une nouvelle pomme apparaît à une nouvelle position - indéfiniment.

Voici le code Javascript :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
// JavaScript Document
 
window.onload = function () {
 
	var canvasWidth = 500;
	var canvasHeight = 300;
	var blockSize = 10; // Taille des blocks
	var ctx;
	var delay = 100;
	var snakee; // serpent
	var applee; // pomme
	var widthInBlocks = canvasWidth / blockSize;// largeur en termes de blocks
	var heightInBlocks = canvasHeight / blockSize;// hauteur en termes de blocks
 
	init();
 
	function init() 
	{
		// Créer le canvas
		var canvas = document.getElementById('canvas');
		canvas.width = canvasWidth;
		canvas.height = canvasHeight;		
 
		// Créer le contexte // serpent
		ctx = canvas.getContext("2d");
		snakee = new Snake([[8,4],[7,4],[6,4],[5,4],[4,4],[3,4]], "right"); // Créer le serpent et sa direction à l'initialisation
		applee = new Apple([10, 10]);
		refreshCanvas();
	}
 
 
	function refreshCanvas() // rafraichir le canvas
	{	
		snakee.advance();
		if(snakee.checkCollision())
			{
				console.log('PERDU !');
				// Game over
			}
		else
			{
			if(snakee.isEatingApple(applee))
			{
				applee.setNewPosition();
				console.log(applee);
						// Serpent mange la pomme
			}
 
			ctx.clearRect(0, 0, canvasWidth, canvasHeight);
			snakee.draw();
			applee.draw();
 
			setTimeout(refreshCanvas,delay); // Exécute la fonction à chaque fois que le temps donné 'delay' est passé
			}
	}
 
 
	function drawBlock(ctx, position)
	{
		var x = position[0] * blockSize;
		var y = position[1] * blockSize;
		ctx.fillRect(x,y,blockSize, blockSize); // remplire un block à la taille de blockSize
	}
 
 
	function Snake(body, direction) //fonction constructeur
	{
		this.body = body;
		this.direction = direction;
		this.draw = function()
		{
			ctx.save();
			ctx.fillStyle = 'red';
			for(var i = 0; i < this.body.length; i++) // passer sur chacun des membres du body du serpent
			{
				drawBlock(ctx, this.body[i]);	
			}
			ctx.restore(); //dessiner sur le ctx et le garder le comme il était avant
		};
 
		// méthode advance pour faire avancer le serpent
		this.advance = function()
		{
			var nextPosition = this.body[0].slice(); // Créer un nouvel élément à partir du format copié
 
			switch(this.direction)
				{
					case "left": nextPosition[0] -= 1;
						break;
					case "right": nextPosition[0] += 1;
						break;
					case "down": nextPosition[1] += 1; 
						break;
					case "up": nextPosition[1] -= 1;
						break;
					default: 
						throw("Direction invalide"); //si erreur, message d'erreur
				}
			this.body.unshift(nextPosition); // rajouter un élément à la première position du array
			this.body.pop(); // enlève le dernier élément du array
		};
		this.setDirection = function(newDirection) 
		{
			var allowedDirections; // directions permises
			switch(this.direction)
				{
					case "left": allowedDirections = ["up", "down"];
					case "right": allowedDirections = ["up", "down"];
						break;
					case "down": allowedDirections = ["left", "right"];
					case "up": allowedDirections = ["left", "right"];
						break;	
					default: 
						throw("Direction invalide"); //si erreur, message d'erreur
				}
			if(allowedDirections.indexOf(newDirection) > -1) // vérifie la direction en retournant une valeur -1 si non et 1 si OK
				{
					this.direction = newDirection; // si direction permise, alors nouvelle direction
				}
		};
		this.checkCollision = function()
		{
			var wallCollision = false;
			var snakeCollision = false;
			var head = this.body[0]; // vérifier si la tête se prend une collision
			var rest = this.body.slice(1); // corps à partir de 1
			var snakeX = head[0];
			var snakeY = head[1];
			var minX = 0;
			var minY = 0;
			var maxX = widthInBlocks - 1; // largeur de l'axe du x en termes de block
			var maxY = heightInBlocks - 1; 
 
			var isNotBetweenHorizontalWalls = snakeX < minX || snakeX > maxX;
			var isNotBetweenVerticalWalls = snakeY < minY || snakeY > maxY;
 
			if(isNotBetweenHorizontalWalls || isNotBetweenVerticalWalls)
				{
					wallCollision = true;
				}
 
			for(var i=0; i < rest.length; i++)
				{
					if(snakeX == rest[i][0] && snakeY == rest[i][1])
						{
							snakeCollision = true;
						}
				}
			return wallCollision || snakeCollision;
		};
 
		this.isEatingApple = function(appleToEat)
		{
			var head = this.body[0]; // tête du serpent
			if(head[0] === appleToEat.position[0] && head[1] === appleToEat.position[1])
				return true;
			else
				return false;
		};
	}
 
 
	function Apple(position)
	{
		this.position = position;
		this.draw = function()
		{
			ctx.save(); // se souvenir des anciens paramètres du Canvas
			ctx.fillStyle = 'green';
			ctx.beginPath;
			var radius = blockSize/2; // taille de la pomme
			var x = this.position[0] * blockSize + radius; // atteindre le point central du block pour tracer le cercle
			var y = this.position[1] * blockSize + radius;
 
			ctx.arc(x,y,radius,0,Math.PI*2, true);
			ctx.fill();
 
			ctx.restore(); // ne pas affecter les autres éléments du Canvas avec save/restore
		};
 
		this.setNewPosition = function()
		{
			var newX = Math.round(Math.random()*(widthInBlocks - 1)); // Position aléatoire
			var newY = Math.round(Math.random()*(heightInBlocks - 1));
			this.position = [newX, newY];
		};
	}
 
 
	document.onkeydown = function handleKeyDown(e)
	{
		var key = e.keyCode; //touche appuyée
		var newDirection;
		switch(key)
			{
				case 37: newDirection = "left";
						break;
				case 38: newDirection = "up";
						break;
				case 39: newDirection = "right";
						break;
				case 40: newDirection = "down";
						break;
				default: return;
			}
		snakee.setDirection(newDirection);
 
	};
 
}
Le HTML quand même :
Code HTML : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<!doctype html>
<html>
 
	<head>
	<meta charset="utf-8">
 
	<link href="https://fonts.googleapis.com/css?family=Gloria+Hallelujah" rel="stylesheet">
	<link href="css/styles.css" rel="stylesheet" type="text/css">
 
	<title>Snake</title>
 
	</head>
 
	<body>
 
		<main>
		<h1>SNAKE</h1>
 
		<canvas id="canvas"></canvas>
 
		<canvas id="score"></canvas>
		</main>
 
		<footer></footer>
 
	</body>
 
	<script type="text/javascript" src="js/canvas.js"></script>
 
</html>

Cela maintenant plusieurs heures que je bloque dessus.. j'espère qu'un esprit extérieur saura m'éclairer ! Merci d'avance.