I'm kind of a novice in the Javascript field, and I'm working on a snake game, where I've been facing an unusual problem: after I restart the game by pressing the restart button, drawn on the canvas board, the snake starts to move by itself, remembering the last key input before game over.
Remember that when you start the game for the first time, the snake begins moving by pressing any key, and the problem after the game reset occurred after I fixed the event listener trigger(when pressing too fast, the snake runs into itself from reverse direction).
I will attach below the code to showcase what I've been working on so far, thanks a lot for your time!
The HTML code
<!-- the snake game section -->
<div data-hover="Press any key to start">
<div >
Score: <p id="score-number">0</p>
</div>
<canvas id="game-board">
</canvas>
</div>
The JS code
const gameBoard = document.getElementById("game-board");
const context = gameBoard.getContext("2d");
let rows = 20;
let cols = 20;
let gridBoard = 20; // per row 30 grids
let gameOver = false;
let snakeSize = 1; // initializing snake's body size
let x = new Array(900);
let y = new Array(900);
gameBoard.height = rows * gridBoard;
gameBoard.width = cols * gridBoard;
for (let i = 0; i < snakeSize; i ){
x[i] = 40 - i*20
y[i] = 40 //the head of the snake
}
// to come up with a random position for the apple
let eatenApple = true;
let appleX;
let appleY;
let score = 0;
let scoreNumber = document.getElementById("score-number");
const path = new Path2D(); // for the reset button
function mainGame(){
//when the snake eats the apple and grows
eatApple();
//movement validation and check the collision
movementValidation();
// keep record of head&body in canvas for movement
move(); // or change the snake position
//to display the snake's head, body, and the apple
display();
setTimeout(mainGame, 150);
}
function display(){
context.clearRect(0,0, gameBoard.width, gameBoard.height);
if(gameOver){
isGameOver();
} else {
//apple
if(eatenApple){
appleRandomPlace();
eatenApple = false;
}
//the apple's head
context.beginPath()
context.fillStyle = "red";
context.fillRect(appleX, appleY, gridBoard / 1, gridBoard / 1);
context.closePath();
for (let i = 0; i < snakeSize; i ){
//the snake's head
if(i === 0){
const snake_head = new Path2D();
context.fillStyle = "#86626E";
snake_head.rect(x[0], y[0], gridBoard / 1, gridBoard / 1);
context.fill(snake_head);
} else {
//the snake's body
const snake_body = new Path2D();
context.fillStyle = "#201335";
context.strokeStyle = "#fff";
context.lineWidth = 3;
snake_body.rect(x[i], y[i], gridBoard / 1, gridBoard / 1);
context.fill(snake_body);
context.stroke(snake_body);
}
}
}
}
function isGameOver(){
//game over text
context.fillStyle = "black";
context.textBaseline = "middle";
context.textAlign = "center";
context.font = "35px Adonay";
context.fillText("game over", gameBoard.width / 2, gameBoard.height / 2);
// the reset button and text
path.rect(150,240,100,40); //x, y, width, height
path.closePath();
context.fillStyle = "black";
context.textBaseline = "middle";
context.textAlign = "center";
context.font = "20px Adonay";
context.strokeStyle = "#0B1D51";
context.lineWidth = 1;
context.fillText("restart", 200, 261, 111, 40);
context.stroke(path);
}
function eatApple(){
if(x[0] === appleX && y[0] === appleY){
snakeSize
eatenApple = true;
score = 1;
scoreNumber.innerText = score;
}
}
function appleRandomPlace(){
appleX = Math.floor(Math.random() * (cols - 5)) * gridBoard 20;
appleY = Math.floor(Math.random() * (rows - 5)) * gridBoard 20;
}
let direction;
let nextDirection;
document.addEventListener("keydown", function(event){
if(event.keyCode === 38 && direction !== "down") {
nextDirection = "up";
}
else if(event.keyCode === 40 && direction !== "up"){
nextDirection = "down";
}
else if(event.keyCode === 37 && direction !== "right"){
nextDirection = "left";
}
else if(event.keyCode === 39 && direction !== "left"){
nextDirection = "right";
}
});
function movementValidation(){
// snake's collision with the walls
if(y[0] >= gameBoard.height / 1.1) {
gameOver = true;
} else if(y[0] < 1) {
gameOver = true;
} else if(x[0] >= gameBoard.width / 1.1) {
gameOver = true;
} else if(x[0] < 1) {
gameOver = true;
}
//x[0] and y[0] represent the head of the snake
// snake eats its own body
for (let i = 1; i < snakeSize; i =1){
if(x[0] === x[i] && y[0] === y[i]){
gameOver = true;
}
}
}
function move(){
// for snake's body
for (let i = snakeSize; i > 0; i--){
x[i] = x[(i-1)];
y[i] = y[(i-1)];
}
// for snake's head
if(nextDirection === "left"){
x[0] -= gridBoard;
}
else if(nextDirection === "right"){
x[0] = gridBoard;
}
else if(nextDirection === "up"){
y[0] -= gridBoard;
}
else if(nextDirection === "down"){
y[0] = gridBoard;
}
direction = nextDirection;
}
function buttonReset(gameBoard, event){
const rect = gameBoard.getBoundingClientRect();
const x = event.clientX - rect.left;
const y = event.clientY - rect.top;
return {x:x, y:y};
}
document.addEventListener("click", function (e){
const x_y = buttonReset(gameBoard, e);
if(context.isPointInPath(path, x_y.x, x_y.y)){
gameOver = false;
snakeSize = 1; // initializing snake's body size
x = new Array(900);
y = new Array(900);
gameBoard.height = rows * gridBoard;
gameBoard.width = cols * gridBoard;
for (let i = 0; i < snakeSize; i ){
x[i] = 40 - i*10
y[i] = 40 //the head of the snake
}
eatenApple = false;
appleX;
appleY;
score = 0;
scoreNumber.innerText = score;
direction;
nextDirection;
display();
move();
eatApple();
movementValidation();
}
}, false);
mainGame();
CodePudding user response:
Reset the movement-related variables at the start of your "new game" function, where you're setting gameOver = false
and so on.
direction = undefined;
nextDirection = undefined;