IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

JavaScript Discussion :

<canvas> Snake Javascript


Sujet :

JavaScript

  1. #1
    Membre régulier
    Homme Profil pro
    Formation dev web
    Inscrit en
    Janvier 2019
    Messages
    7
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 29
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Formation dev web

    Informations forums :
    Inscription : Janvier 2019
    Messages : 7
    Par défaut <canvas> Snake Javascript
    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.

  2. #2
    Membre extrêmement actif
    Avatar de Sodium
    Femme Profil pro
    Développeuse web
    Inscrit en
    Avril 2014
    Messages
    2 324
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeuse web

    Informations forums :
    Inscription : Avril 2014
    Messages : 2 324
    Billets dans le blog
    1
    Par défaut
    J'ai lu ton code en diagonale, je pense que ta boucle n'efface pas l'ancienne pomme lorsque tu la fait apparaître ailleurs.
    Un canvas est un simple ensemble de pixels, tout ce que tu dessines dessus y reste tant que tu ne l'as pas effacé, ce qui peut être assez compliqué à gérer rapidement.

    Ce que je te conseille, c'est plutôt que de passer par des save et restore, c'est de redessiner le canvas à chaque frame. Donc tu stockes les données de ton serpent, celles de ta pomme.
    A chaque frame tu effaces tout le canvas, tu redessines le sol, les murs, puis le serpent et la pomme. Bien entendu tu gères tout ça avec des fonctions de façon a pouvoir les appeler les unes à la suite des autres de manière bien propre.

    Sinon il existe des librairies qui peuvent sérieusement te simplifier la vie comme CreateJS que j'avais utilisé à une époque pour faire un snake justement entre autres : https://www.createjs.com/easeljs
    Si tu fais partie des dinosaures comme moi à avoir programmer en Flash, le fonctionnement est assez similaire. Elle permet entre autre de gérer des sprites que tu peux déplacer facilement, la librairie se charge ensuite de repeindre le canvas avec les limitations de celui-ci.

  3. #3
    Modérateur

    Avatar de NoSmoking
    Homme Profil pro
    Inscrit en
    Janvier 2011
    Messages
    17 198
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Janvier 2011
    Messages : 17 198
    Par défaut
    Bonjour,
    ligne 170 de ton script il manque les parenthèses à la méthode beginPath().
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    this.draw = function()
        {
          ctx.save();
          ctx.fillStyle = 'green';
          ctx.beginPath();                             // manque parenthèses ICI
          var radius = blockSize/2;
          var x = this.position[0] * blockSize + radius;
          var y = this.position[1] * blockSize + radius;
          ctx.arc(x,y,radius,0,Math.PI*2, true);
          ctx.fill();
          ctx.restore();
        };

Discussions similaires

  1. Carte (terrain) de jeu avec Canvas et JavaScript
    Par toshiba1996 dans le forum Général JavaScript
    Réponses: 11
    Dernier message: 20/02/2017, 20h35
  2. Jeux en canvas et javascript
    Par mOscar007 dans le forum Général JavaScript
    Réponses: 24
    Dernier message: 03/01/2015, 14h43
  3. [HTML 5] Canvas et Javascript
    Par manakeo dans le forum Balisage (X)HTML et validation W3C
    Réponses: 2
    Dernier message: 03/12/2011, 15h54
  4. Canvas (HTML5 & JavaScript)
    Par twiotrie dans le forum Balisage (X)HTML et validation W3C
    Réponses: 1
    Dernier message: 03/01/2011, 17h24
  5. [Image] Un sprite dans canvas avec javascript?
    Par themoye dans le forum Général JavaScript
    Réponses: 2
    Dernier message: 15/09/2010, 18h44

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo