dan

dan

groovin'

Implementing screen wrap

When the snake runs out of bounds to the right side, we want to teleport it back to the left side of the grid. The same concept applies for the other sides of the screen. We need to check each element of the player array to see if any of them have gone out of bounds. Since arrays in JavaScipt are 0-based, out of bounds on the left side of the x-axis will be -1, but on the right side, it will be 10, which is the number of tiles on the x axis. If an element of the snake is out of bounds on the left side, we want it to move to the 9th tile on the grid. If an element of the snake is out of bounds on the right side, we want to move it to the 0th tile on the grid. We will use this logic on the y axis as well in the code snippet below.

for(let i = 0; i < player.length; ++i) {
  if(player[i].x == tilesX)
    player[i].x = 0;
  else if(player[i].x == -1)
    player[i].x = tilesX -1;
  
  if(player[i].y == tilesY) 
    player[i].y = 0;
  else if(player[i].y == -1)
    player[i].y = tilesY -1;
}
Put this at the bottom of the update function

If you test the code out, you will be able to infinitely travel in any direction across the grid!

Game over

Right now, the player can move around with no threat of danger. First we need a variable to store whether the game is over or not. You can put this near the top of the file with the other variables.

let gameOver = false;

Let's write a test to see if the snake has collided with itself. We want to know if the head of the snake is inside the same tile as any other element in the snake. We can put this within the loop that we just created.

if(i > 0 && head.x == player[i].x && head.y == player[i].y) {
  gameOver = true;
}

Note

Notice that the if statement checks to see if i > 0. This is to make sure that we are not comparing the head to itself.

We are setting the gameOver state, but we aren't doing anything with it. For now, let's stop the update loop if the game is over. In a subsequent chapter, we will render a gameover screen.

if(lastKey == undefined || gameOver)
  return;

To make sure we're on the same page, your update function should look like this:

function update() {
  if(lastKey == undefined || gameOver)
    return;
 
  // Remove the last element in the array
  player.pop();
 
  // This is a confusing line of code. We are copying the head of the snake at player[0]
  // into an empty object {} and returning it to the variable `head`.
  // If we use `head = player[0]`, we would be referencing `player[0]` instead of copying it.
  let head = Object.assign({}, player[0]);
 
  if(lastKey == "ArrowLeft")
    --head.x;
  else if(lastKey == "ArrowRight")
    ++head.x;
  else if(lastKey == "ArrowUp")
    --head.y;
  else if(lastKey == "ArrowDown")
    ++head.y;
 
  // Add the head of the snake to the beginning of the array
  player.unshift(head);
 
  for(let i = 0; i < player.length; ++i) {
    // Check if the snake has hit itself
    if(i > 0 && head.x == player[i].x && head.y == player[i].y)
      gameOver = true;
		
    // Check if the snake is out of bounds
    if(player[i].x == tilesX)
      player[i].x = 0;
    else if(player[i].x == -1)
      player[i].x = tilesX -1;
		
    if(player[i].y == tilesY) 
      player[i].y = 0;
    else if(player[i].y == -1)
      player[i].y = tilesY -1;
  }
}

Sneak peek

In the next chapter, we will introduce the goal of the entire game - the apple!