I am trying to create a simple snake game.
(function() { var canvas = document.getElementById('canvas'), ctx = canvas.getContext('2d'), x = 0, y = 0, speed = 2; x_move = speed, y_move = 0, food_position_x = Math.floor(Math.random() * canvas.width / 10) * 10, food_position_y = Math.floor(Math.random() * canvas.height / 10) * 10, size_x = 10; function eat() { console.log('food_x:' + food_position_x + ' x:' + x + ' / food_y:' + food_position_y + ' y:' + y); if (Math.floor(y / 10) * 10 == food_position_y && Math.floor(x / 10) *10 == food_position_x) { size_x += 2; //throw new Error("MATCH!"); // This is not an error. Just trying to stop the script } } // Drawing function draw() { eat(); requestAnimationFrame(function() { draw(); }); // Draw the snake ctx.beginPath(); ctx.rect(Math.floor(x/10)*10, Math.floor(y/10)*10, size_x, 10); ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.fillStyle = '#ffffff'; ctx.fill(); ctx.closePath(); // Draw the food ctx.beginPath(); ctx.rect(Math.floor(food_position_x/10)*10, Math.floor(food_position_y/10)*10, 10, 10); ctx.fillStyle = "blue"; ctx.fill(); ctx.closePath(); // Increase the value of x and y in order to animate x = x + x_move; y = y + y_move; } draw(); // Key Pressing document.addEventListener('keydown', function(event) { switch(event.keyCode) { case 40: // Moving down if (x_move != 0 && y_move != -1) { x_move = 0; y_move = speed; } break; case 39: // Moving right if (x_move != -1 && y_move != 0) { x_move = speed; y_move = 0; } break; case 38: // Moving top if (x_move != 0 && y_move != 1) { x_move = 0; y_move = -speed; } break; case 37: // Moving left if (x_move != 1 && y_move != 0) { x_move = -speed; y_move = 0; } break; } }); })();
canvas { background-color: #000022 }
<canvas id="canvas" width="400" height="400"></canvas>
jsfiddle
The problem
Every time when I catch the food, the snake becomes longer but when you press the down or up key, it moves horizontally.
Maybe a solution
This is what I believe the solution could be: The snake should be an array! Every time when the key is pressed, define the position of HEAD of snake and move the snake step by step, because it is an array. So the body follows the head. But in this case, I have no idea how to make an array from it.
Maybe there are other solutions. Any helps would be appreciated!
Most snakes slither on the ground in a straight line, often curving as they slide, but their direction is straight. However, as its name suggests, the sidewinder snake moves sideways, something physics professor Jennifer Rieser says is because of its sandy home.
Sidewinding movement If you're a snake and on sand or mud then this is the movement you use! By contracting their muscles and pushing off only 2 contact points, they launch their body throwing the head forward and the rest of the body follows moving sideways. Hence the name sidewinding movement.
For several decades workers have identified four major modes of snake locomotion: rectilinear, lateral undulation, sidewinding, and concertina locomotion (Mosauer 1932; Gray 1946; Lissmann 1950; Gans 1962; Jayne 1986).
For several decades different types of snake locomotion have been categorized as one of four major modes: rectilinear, lateral undulation, sidewinding, and concertina. Recent empirical work shows that the scheme of four modes of snake locomotion is overly conservative.
You need to maintain an array
of the points currently occupied by the snake body, and add new point (unshift
) to the array as the snake approaches and remove point from the back of the array (pop
). The following code is a starter, you need to make it your own :).
(function () { const COLORS={ SNAKE:'#ff7bf5', FOOD:'blue' }; var canvas = document.getElementById('canvas'), ctx = canvas.getContext('2d'); var snake=[], score=0; var x, y, food_position_x, food_position_y, x_move, y_move; var frameCount=0, framesRequiredToMove=10; //the less the framesToMove the faster the sname moves function draw(){ if(++frameCount==framesRequiredToMove){ frameCount=0; move(); } requestAnimationFrame(draw); } function init(){ snake = [{x:3,y:0},{x:2,y:0},{x:1,y:0},{x:0,y:0}]; snake.forEach((p)=>{plot(p.x,p.y,COLORS.SNAKE)}) x=snake[0].x;y=snake[0].y; score=0;x_move=1;y_move=0; scoreboard.innerText=score; newfood(); setTimeout(draw,1000); } function plot(x,y,color){ ctx.beginPath(); ctx.rect(x * 10, y * 10, 10, 10); ctx.fillStyle = color; ctx.fill(); ctx.closePath(); } function move(){ snakepx.innerText = x; snakepy.innerText = y; x = x + x_move; y = y + y_move; // Advance The Snake plot(x,y,COLORS.SNAKE); snake.unshift({x:x,y:y}); // Check food encounter if(x==food_position_x && y==food_position_y){ scoreboard.innerText=++score; newfood(); } else{ var last=snake.pop(); ctx.clearRect(last.x * 10, last.y * 10, 10, 10); } } function newfood(){ food_position_x=Math.floor(Math.random() * canvas.width / 10); food_position_y=Math.floor(Math.random() * canvas.height / 10); plot(food_position_x,food_position_y,COLORS.FOOD); foodpx.innerText = food_position_x; foodpy.innerText = food_position_y; } init(); // Key Pressing document.addEventListener('keydown', function (event) { event.preventDefault(); switch (event.keyCode) { case 40: // Moving down if (x_move != 0 && y_move != -1) { x_move = 0; y_move = 1; } break; case 39: // Moving right if (x_move != -1 && y_move != 0) { x_move = 1; y_move = 0; } break; case 38: // Moving top if (x_move != 0 && y_move != 1) { x_move = 0; y_move = -1; } break; case 37: // Moving left if (x_move != 1 && y_move != 0) { x_move = -1; y_move = 0; } break; } }); })();
canvas { background-color: #000022; float: left; }
<canvas id="canvas" width="400" height="180"></canvas> <div style="margin-left: 410px"> Snake: (<span id="snakepx"></span>, <span id="snakepy"></span>)<br> Food: (<span id="foodpx"></span>, <span id="foodpy"></span>)<br> Score: <span id="scoreboard"></span> </div>
Well as I had some free time to spare I created my own JS snake to demonstrate you how it can be done. Most important parts are in this.snakeBody where array of body is stored and this.moveForward() where you can see how body is updated.
https://jsfiddle.net/nooorz24/p8xtdv3h/13/
moveForward: function() { var next = this.getNextfieldValue(); if (next == "frame" || next == "body") { console.log("You lose!") this.isAlive = false; } else { var newHead = this.getNextfieldCoords(); this.draw.snake(newHead.x, newHead.y); this.body.unshift(newHead); if (next == "food") { this.generateFood(); this.snakeSize++; } else { var last = this.body.pop(); this.draw.empty(last.x, last.y); } } },
I tried to make it as readable as I could, but note that this is unfinished example and would need need loads of improvements to be a playable game
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With