<body>
  <div id="mainTitle">Javascript Snake Game</div>
  <div id="title">Score: <span id="score">0</span></div>
  
  <canvas id="canvas1" width="400" height="400"><canvas>
</body>
body {
  background-color: #03011f;
  font-family: "Source Sans Pro";
  color: #6cacc5;
  text-align: center;
}

#canvas1 {
  position: absolute;
  top: 50%; 
  left: 50%;
  transform: translate(-50%, -50%);
}
#mainTitle {
  text-align: center;
  font-size: 60px;
}
#score, #title {
  text-align: left;
  font-size: 40px;
}
const board_border = 'black';
const board_background = 'black';
const snake_col = 'lightblue';
const snake_border = 'darkblue';

let snake = [{x:200, y:200},  {x:190, y:200}, {x:180, y:200},{x:170, y:200}, {x:160, y:200}];

let foodX;
let foodY;
let score = 0;
let changingDirection = false;
let dx = 10;
let dy = 0;

const snakeboard = document.getElementById("canvas1");
const ctx = snakeboard.getContext('2d');
main();
generateFood();

document.addEventListener("keydown", changeDirection);


function main() {
  if (hasGameEnded()) return;
  changingDirection = false;
  setTimeout(function onTick() 
   {    
     clearCanvas();    
     moveSnake();  
     drawSnake();
     drawFood();
     // Call main again
     main();
   }, 100)
}

function clearCanvas(){
  ctx.fillStyle = board_background;
  ctx.strokeStyle = board_border;            ctx.fillRect(0,0,snakeboard.width, snakeboard.height);
  ctx.strokeRect(0,0,snakeboard.width, snakeboard.height);
}

function drawSnake() {
  snake.forEach(drawSnakePart);
}

function drawSnakePart(snakePart) {
  ctx.fillStyle = snake_col;
  ctx.strokeStyle = snake_border;
  ctx.fillRect(snakePart.x, snakePart.y, 10, 10);
  ctx.strokeRect(snakePart.x, snakePart.y, 10, 10);
}

function hasGameEnded(){
  for(let i = 4; i< snake.length; i++){
    const hasCollided = snake[i].x === snake[0].x && snake[i].y === snake[0].y;
    if (hasCollided){
      return true;
    }
  }
  const hitLeftWall = snake[0].x < 0;
  const hitRightWall = snake[0].x > snakeboard.width - 10;
  const hitTopWall = snake[0].y < 0;
  const hitBottomWall = snake[0].y > snakeboard.height - 10;
  
  return hitLeftWall || hitRightWall || hitTopWall || hitBottomWall;
  alert("Game over");
}

function changeDirection(event) {
  const LEFT_KEY = 37;
  const RIGHT_KEY = 39;
  const UP_KEY = 38;
  const DOWN_KEY = 40;
  
  if(changingDirection) {
    return;
  }
  changingDirection = true;
  const keyPressed = event.keyCode;
  const goingUp = dy === -10;
  const goingDown = dy === 10;
  const goingRight = dx === 10;
  const goingLeft = dx === -10;
  
  if(keyPressed === LEFT_KEY && !goingRight){
    dx = -10;
    dy = 0;
  }
  if (keyPressed === UP_KEY && !goingDown){
    dx = 0;
    dy = -10;
  }
  if(keyPressed === RIGHT_KEY && !goingLeft){
    dx = 10;
    dy = 0;
  }
  if(keyPressed === DOWN_KEY && !goingUp){
    dx = 0;
    dy = 10;
  }
}

function randomFood(min, max){
  return Math.round((Math.random() * (max-min) + min) / 10) * 10;
}

function generateFood() {
  foodX = randomFood(0, snakeboard.width - 10);
  foodY = randomFood(0, snakeboard.height - 10);
  snake.forEach(function hasSnakeEatenFood(part){
    const hasEaten = part.x == foodX && part.y == foodY;
    if (hasEaten) {
      generateFood();
    }
  })
}

function drawFood() {
  ctx.fillStyle = 'lightgreen';
  ctx.strokeStyle = 'darkgreen';
  ctx.fillRect(foodX, foodY, 10, 10);
  ctx.strokeRect(foodX, foodY, 10, 10);
}

function moveSnake() {
  const head = {x: snake[0].x + dx, y: snake[0].y + dy};
  snake.unshift(head);
  const hasEatenFood = snake[0].x === foodX && snake[0].y === foodY;
  if (hasEatenFood) {
    score += 10;
    document.getElementById('score').innerHTML = score;
    generateFood();
  } else {
    snake.pop();
  }
  
}



External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.