I am trying to do a javascript snake project, and I need to check if the same keyboard key is pressed more than once.
I wrote the code so when you press the correct key, the snake moves a direction, however if you spam the key, it goes really fast. Is there any way to prevent it from doing so?
Code:
HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="./style.css">
<script src="./game.js" defer></script>
<title>Snake Game</title>
</head>
<body>
<div id="game-board">
<div id="snake"></div>
<div id="apple"></div>
</div>
</body>
</html>
Javascript:
let apple = document.getElementById('apple');
let snake = document.getElementById('snake');
let snakeColumnStart = 11;
let snakeRowStart = 11;
let forward = false;
let right = false;
let back = false;
let left = false;
let gameOver = false;
const getApplePos = (min, max) => {
return Math.floor(Math.random() * (max - min 1) min);
}
const setApplePos = () => {
const gridColumnStart = getApplePos(1, 20);
const gridColumnEnd = gridColumnStart 1;
const gridRowStart = getApplePos(1, 20);
const gridRowEnd = gridRowStart 1;
apple.style.gridArea = `${gridRowStart} / ${gridColumnStart} / ${gridRowEnd} / ${gridColumnEnd}`;
console.log(gridColumnStart)
console.log(gridRowStart)
}
const setSnakePos = () => {
let snakeColumnEnd = snakeColumnStart 1;
let snakeRowEnd = snakeRowStart 1;
snake.style.gridArea = `${snakeRowStart} / ${snakeColumnStart} / ${snakeRowEnd} / ${snakeColumnEnd}`;
}
const forwardLoop = () => {
setTimeout(() => {
if (snakeRowStart <= 20 && snakeRowStart >= -20 && snakeColumnStart >= -20 && snakeColumnStart <= 20 && forward) {
snakeRowStart = -1;
setSnakePos();
forwardLoop()
}
else if (!forward) {
return ;
}
else{
console.log("game over");
}
}, 1000)
}
const rightLoop = () => {
setTimeout(() => {
if (snakeRowStart <= 20 && snakeRowStart >= -20 && snakeColumnStart >= -20 && snakeColumnStart <= 20 && right) {
snakeColumnStart = 1;
setSnakePos();
rightLoop()
}
else if (!right) {
return ;
}
else{
console.log("game over");
}
}, 1000)
}
const leftLoop = () => {
setTimeout(() => {
if (snakeRowStart <= 20 && snakeRowStart >= -20 && snakeColumnStart >= -20 && snakeColumnStart <= 20 && left) {
snakeColumnStart = -1;
setSnakePos();
leftLoop()
}
else if (!left) {
return ;
}
else{
console.log("game over");
}
}, 1000)
}
const backLoop = () => {
setTimeout(() => {
if (snakeRowStart <= 20 && snakeRowStart >= -20 && snakeColumnStart >= -20 && snakeColumnStart <= 20 && back) {
snakeRowStart = 1;
setSnakePos();
backLoop()
}
else if (!back) {
return ;
}
else{
console.log("game over");
}
}, 1000)
}
setSnakePos();
setApplePos();
window.addEventListener('keydown', (e) => {
forward = false;
right = false;
back = false;
left = false;
if (e.key == 'w'){
forward = true;
forwardLoop();
}
if (e.key == "d"){
right = true;
rightLoop();
}
if (e.key == "a"){
left = true;
leftLoop();
}
if (e.key == "s"){
back = true;
backLoop();
}
})
Css:
body{
height:100vh;
width:100vw;
display: flex;
justify-content: center;
align-items: center;
margin:0;
background-color: darkgreen;
}
#game-board{
background-color: green;
width:500px;
height:500px;
display: grid;
grid-template-rows: repeat(20, 1fr);
grid-template-columns: repeat(20, 1fr);
}
.snake{
background-color: rgb(65, 65, 255);
border: 2px solid black;
border-radius: 5px;
z-index: 99999;
}
.apple{
background-color: rgb(248, 24, 24);
border: 2px solid black;
border-radius: 5px;
}
CodePudding user response:
You can use a flag variable to prevent spam key pressing.
forward = false;
right = false;
back = false;
left = false;
window.addEventListener('keydown', (e) => {
if (e.key == 'w' && !forward){
forward = true;
right = false;
back = false;
left = false;
forwardLoop();
}
if (e.key == "d" && !right){
right = true;
forward = false;
back = false;
left = false;
rightLoop();
}
if (e.key == "a" && !left){
left = true;
forward = false;
right = false;
back = false;
leftLoop();
}
if (e.key == "s" && !back){
back = true;
forward = false;
right = false;
left = false;
backLoop();
}
})
As above you can declare flags to control entry to function.
CodePudding user response:
Check if the key was pressed before starting another loop:
if (e.key == 'w' && !forward){
forward = true;
forwardLoop();
}
Or clear the existing loop before starting another one: https://developer.mozilla.org/en-US/docs/Web/API/clearTimeout
And I think you should be using setInterval
instead of setTimeout
.
You also dont need four different boolean variables to determine direction, you could have just one: currentDirection = 'down'
.