Javascript check if a keyboard key is pressed more than once

Issue

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 class="snake" id="snake"></div>
    <div class="apple" 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;
}

Solution

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'.

Answered By – Alan P.

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published