---
title: Snake Game using HTML5 Canvas tag
teaser: 'Learn how to iteratively develop the Snake Game for the web browser.

  '
tags: css,html,javascript,new bamboo,web
author: Paul Jensen
published_on: 2009-12-31
---

_This post was originally published on the New Bamboo blog, before [New Bamboo
joined thoughtbot in London][new-bamboo-thoughtbot]._

---

## Introduction

The HTML5 spec is currently in draft, but is already being supported by web
browsers like Apple's Safari, Mozilla Firefox, and Opera. One of the wonderful
new features of the spec is the canvas tag, a html element which combined with
the javascript api allows you to draw graphics and animate them. I'm going to
demonstrate one of the many cool things you can do with the canvas tag by
remaking the Snake mobile phone game with it. You can view the [snake source]
and play the [snake game].

## Getting Started

To start with, you'll want to create a html file with the following markup:

```html
<html>
  <head>
    <title>Snake</title>
    <link href='/reset.css' rel='stylesheet'>
    <link href='/master.css' rel='stylesheet'>
    <script src='snake.js' type='text/javascript'></script>
  </head>
  <body>
    <canvas id="canvas" width="400" height="300"></canvas>
  </body>
</html>
```

For the reset.css stylesheet:

```css
html, body div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a abbr, acronym, address, big, cite, code, del, dfn, em, font, img, ins, kdb, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td {
  margin: 0;
  padding: 0;
  font-size: 100%;
  vertical-align: baseline;
  border: 0;
  outline: 0;
  background: transparent;
}

ol, ul {
  list-style: none;
}

blockquote, q {
  quotes: none;
}

a, a:hover {
  text-decoration: none;
}

table {
  border-collapse: collapse;
  border-spacing: none;
}
```

For the master.css stylesheet:

```css
body {
  background: #111;
}

canvas {
  border: solid 1px red;
}
```

This sets up a black web page, with a red border around the canvas tag.

![](https://images.thoughtbot.com/new-bamboo/blog/html5-canvas-snake-game/NiWJB361SXqhsxBboWgt_image_1.jpg)

## Detecting Canvas support

Unfortunately, not all web browsers support canvas yet (_cough_ IE), so the
first thing we should do is check if the browser supports it. The snake.js file
is where we will put the code to check for canvas support.

```javascript
function checkSupported() {
  canvas = document.getElementById('canvas');
  if (canvas.getContext){
    ctx = canvas.getContext('2d');
    // Canvas is supported
  } else {
    // Canvas is not supported
    alert("We're sorry, but your browser does not support the canvas tag. Please use any web browser other than Internet Explorer.");
  }
}
```

And to make this code execute when the web page loads, adjust the body tag so it
reads like this:

```html
<body onload="checkSupported();">
```

## Drawing

Now, I'm interested in drawing objects on the canvas, namely the snake. From
what I remember from my first mobile phone (a Nokia 3210), the snake was a chain
of squares which you could move in four directions, so let's start by drawing a
square:

```javascript
// This sets the fill color to red
ctx.fillStyle = "rgb(200,0,0)";

// This sets some variables for demonstration purposes
var x = 50;
var y = 50;
var width = 10;
var height = 10;

// This draws a square with the parameters from the variables set above
ctx.fillRect(x, y, width, height);
```

If you put this javascript code in the canvas-supported section of the IF block,
then you should see the following result below:

![](https://images.thoughtbot.com/new-bamboo/blog/html5-canvas-snake-game/e82rlFnfQba7TUNRRovB_image_2.jpg)

A nice little red square somewhere in the top left corner of the canvas. This
shows you how easy it is to draw rectangular objects on the canvas. There are
also options to draw the stroke of a rectangle, as well as clear a rectangle:

```javascript
strokeRect(x,y,w,h);
clearRect(x,y,w,h);
```

## Movement

Now that I know how to draw squares, I want to move that square, or at least
give the impression of a moving square. The snake can move up, down, left and
right. In javascript, we want to capture keyboard keys being hit, and use those
keys to interact with the canvas.

To capture the keystrokes, I use the following javascript code:

```javascript
document.onkeydown = function(event) {
  var keyCode;

  if(event == null)
  {
    keyCode = window.event.keyCode;
  }
  else
  {
    keyCode = event.keyCode;
  }

  switch(keyCode)
  {
    // left
    case 37:
      // action when pressing left key
      break;

    // up
    case 38:
      // action when pressing up key
      break;

    // right
    case 39:
      // action when pressing right key
      break;

    // down
    case 40:
      // action when pressing down key
      break;

    default:
      break;
  }
}
```

This code sets up the ability to capture the user pressing the up, down, left,
and right keys on the keyboard, providing the controls needed to move the Snake
around the canvas.

When we press a key, we want to draw a new square going in that direction. To
match the direction, we need to know the following:

- What is the current position of the snake's head
- What direction do we want to go, which is given by the key press

So, we need a variable to record the position of the snake's head, and when we
press a key, we draw a new square, whose position is the offset of the direction
from the current position of the snake's head.

In the canvas-supported part of the IF block, fill in the following code:

```javascript
// The current position of the Snake's head, as xy coordinates
this.currentPosition = [50, 50];

// Sets the grid dimensions as one value
this.gridSize = 10;
```

We're going to use these global variables to set the starting point for the
snake, as well as the grid size, which defines both how far they move in a
direction, as well as how large each square will be.

Now, we want to adjust the keydown switch statement to generate new xy
coordinates, which we will then provide to the fillRect argument to create a new
square:

```javascript
switch(keyCode)
{
  // left
  case 37:
    // set new position, and draw square at that position.
    currentPosition['x'] = currentPosition['x'] - gridSize;
    ctx.fillRect(currentPosition['x'], currentPosition['y'], gridSize, gridSize);
    break;

  // up
  case 38:
    currentPosition['y'] = currentPosition['y'] - gridSize;
    ctx.fillRect(currentPosition['x'], currentPosition['y'], gridSize, gridSize);
    break;

  // right
  case 39:
    currentPosition['x'] = currentPosition['x'] + gridSize;
    ctx.fillRect(currentPosition['x'], currentPosition['y'], gridSize, gridSize);
    break;

  // down
  case 40:
    currentPosition['y'] = currentPosition['y'] + gridSize;
    ctx.fillRect(currentPosition['x'], currentPosition['y'], gridSize, gridSize);
    break;

  default:
    break;
}
```

You should see something like this below:

![](https://images.thoughtbot.com/new-bamboo/blog/html5-canvas-snake-game/KqgJMKlyTxqRFBUYPzga_image_3.jpg)

If you were successful, you should be able to draw a line that can go in all
four directions. You can also change the code that drew the initial square in
the IF block so that it looks like this:

```javascript
ctx.fillRect(currentPosition['x'], currentPosition['y'], gridSize, gridSize);
```

You'll notice that this line is commonly repeated in several places within the
code. I'm going to create a function for convenience, which does seem a bit much
for a 1 line method, but will make the code easier to read:

```javascript
function drawSnake() {
  ctx.fillRect(currentPosition['x'], currentPosition['y'], gridSize, gridSize);
}
```

You can go through the code and replace those lines as appropriate.

## Snake keeps moving

When you play the Snake mobile phone game, you can control the direction of the
snake, but not it's speed, that remains a constant, and means that you have to
focus on guiding the snake around the area so as to not bump into itself. It's a
bit like [the guy in Australia who had to steer his car as the cruise control
locked][australia-car-guy].

To provide this functionality, we need to do two things:

- Have a new variable record what direction the snake is going in
- Make a timed loop that will execute a function to move the snake in that direction

So, first things first, we create a new global variable, called direction:

```javascript
direction = 'right';
```

Now, we need to execute an animation that moves the Snake in that direction, put
this in the canvas-supported IF block:

```javascript
setInterval(moveSnake,100);
```

Now, add this function somewhere towards the bottom of the code:

```javascript
function moveSnake(){
  switch(direction){
    case 'up':
      currentPosition['y'] = currentPosition['y'] - gridSize;
      drawSnake();
      break;

    case 'down':
      currentPosition['y'] = currentPosition['y'] + gridSize;
      drawSnake();
      break;

    case 'left':
      currentPosition['x'] = currentPosition['x'] - gridSize;
      drawSnake();
      break;

    case 'right':
      currentPosition['x'] = currentPosition['x'] + gridSize;
      drawSnake();
      break;
  }
}
```

You should see the Snake moving right, which is good, but it seems that despite
our insisting, the Snake is determined to go right, right out of the canvas in
fact. This highlights that a) we haven't associated keystrokes with a change in
direction, and b) The snake is free to escape the canvas, which it shouldn't be.
The latter issue we will deal with later, but first, let's associate the
keystrokes with the direction.

Simply set the direction variable with the keystoke:

```javascript
switch(keyCode)
{
  // left
  case 37:
    // set new position, and draw square at that position.

    direction = 'left';

    currentPosition['x'] = currentPosition['x'] - gridSize;
    drawSnake();
    break;
}
```

Now, let's set the boundaries for the Snake to move within.

## Setting boundary on movement

We want our Snake's movements to be restricted to within the boundaries of the
canvas tag, therefore we need to do the following:

- Find out what the canvas boundaries are
- Detect if the snake's position will go out of the boundary
- and if it will, redirect it to an alternative direction

The first step is simple:

```javascript
canvas.width;
canvas.height;
```

The html attributes we defined for the canvas tag are available in javascript,
so we will refer to them in that way. When the snake moves down or right, we
then want to check whether the new position's x or y value is greater than the
canvas' width or height. If it is, then we don't draw the new square. Instead,
we choose to move in a different direction, so as to keep the momentum going.
The same principle takes effect if the current position's x or y value is less
than 0 when the snake moves up or left.

I have to admit, at this point I took the opportunity to refactor my code, so
that I kept the logic in one place. I started by turning the calculated
positions for up, down, left, and right into functions:

```javascript
function leftPosition(){
 return currentPosition['x'] - gridSize;
}

function rightPosition(){
  return currentPosition['x'] + gridSize;
}

function upPosition(){
  return currentPosition['y'] - gridSize;
}

function downPosition(){
  return currentPosition['y'] + gridSize;
}
```

The calculated position functions would then be used for the logic to determine
if the snake could move in a certain direction, as well as for setting the
current position for which to move to.

The next step would be to wrap the boundary logic, direction setter, current
position setter and drawShape function call within named functions:

```javascript
function moveUp(){
  if (upPosition() >= 0) {
    executeMove('up', 'y', upPosition());
  }
}

function moveDown(){
  if (downPosition() < canvas.height) {
    executeMove('down', 'y', downPosition());
  }
}

function moveLeft(){
  if (leftPosition() >= 0) {
    executeMove('left', 'x', leftPosition());
  }
}

function moveRight(){
  if (rightPosition() < canvas.width) {
    executeMove('right', 'x', rightPosition());
  }
}

function executeMove(dirValue, axisType, axisValue) {
  direction = dirValue;
  currentPosition[axisType] = axisValue;
  drawSnake();
}
```

The first four methods are similar in setup. The first line calls an IF
statement to check if the movement in that direction will set the current
position inside of the canvas area. If it does, then the second line is
executed, pass 3 parameters to the executeMove function.

The executeMove function is a refactoring of the same code that was encapsulated
in the moveUp/moveDown/moveLeft/moveRight functions. It sets the direction, then
it sets the currentPosition according to the axis type and the axis value passed
in, then it draws the square representing the head of the snake.

Finally, we can now clean up a lot of common code, so now our keystroke calls
and automated snake movements look like this:

```javascript
document.onkeydown = function(event) {
  var keyCode;

  if(event == null)
  {
    keyCode = window.event.keyCode;
  }
  else
  {
    keyCode = event.keyCode;
  }

  switch(keyCode)
  {
    // left
    case 37:
      moveLeft();
      break;

    // up
    case 38:
      moveUp();
      break;

    // right
    case 39:
      moveRight();
      break;

    // down
    case 40:
      moveDown();
      break;

    default:
      break;
  }
}

function moveSnake(){
  switch(direction){
    case 'up':
      moveUp();
      break;

    case 'down':
      moveDown();
      break;

    case 'left':
      moveLeft();
      break;

    case 'right':
      moveRight();
      break;
  }
}
```

Nice and clean. What you should see now is that the Snake moves by itself, and
when it gets to the edge of the canvas, it actually stops at that point. You can
test this by waiting a few seconds after the snake has reaches the edge, then
press a key going to either side of the snake, and you will notice that the
snake then traverses immediately from that point in the given direction, it has
not escaped from the canvas.

This is good so far, but what we want to happen is for the snake to
automatically move to either side once it hits an edge and cannot go further. We
do this by using the following code:

```javascript
function whichWayToGo(axisType){
  if (axisType=='x') {
    a = (currentPosition['x'] > canvas.width / 2) ? moveLeft() : moveRight();
  } else {
    a = (currentPosition['y'] > canvas.height / 2) ? moveUp() : moveDown();
  }
}
```

This code takes an axis type, and then works out which way to go based on the
current position. So, for example if the snake has hit the right edge of the
canvas, then the function is passed a `y` parameter, telling the function it
needs to move either up or down. This function will then check if the current
position is above or below the middle of the canvas. If it's above, it will move
down, and vice versa. The sample principles apply for the horizontal case.

So, with that function, adjust the moveUp/moveDown/moveLeft/moveRight functions
as shown below:

```javascript
function moveUp(){
  if (upPosition() >= 0) {
    executeMove('up', 'y', upPosition());
  } else {
    whichWayToGo('x');
  }
}

function moveDown(){
  if (downPosition() < canvas.height) {
    executeMove('down', 'y', downPosition());
  } else {
    whichWayToGo('x');
  }
}

function moveLeft(){
  if (leftPosition() >= 0) {
    executeMove('left', 'x', leftPosition());
  } else {
    whichWayToGo('y');
  }
}

function moveRight(){
  if (rightPosition() < canvas.width) {
    executeMove('right', 'x', rightPosition());
  } else {
    whichWayToGo('y');
  }
}
```

If you now reload the page, you will see that the Snake keeps moving when it
hits an edge, and cleverly opts to head in the direction furthest from an edge.

## Pulling the Snake's body along

It's starting to get there, the Snake looks great, even a bit intelligent as he,
or she, sees an edge. That's all good, but right now the Snake has a backside
that doesn't move, or to quote Homer Simpson (and I kid you not, this is in one
of the early episodes), "Marge, you got a butt that won't quit". It needs to
drag it's body along, not draw an infinite line, so that's what we're going to
do.

You'll notice that I thought about this earlier on when I came up with the
drawSnake() function name. I wanted to have a placeholder where I would draw the
Snake's body. Remember when I referred to the Snake as looking like 'a chain of
squares'? That's exactly what the snake will be, a chain of squares.

The idea is to have an array of xy coordinates that will represent all the
square points which the Snake body occupies:

```javascript
snakeBody = [];
```

and adjust the drawSnake function so it looks like this:

```javascript
function drawSnake() {
  snakeBody.push([currentPosition['x'], currentPosition['y']]);
  ctx.fillRect(currentPosition['x'], currentPosition['y'], gridSize, gridSize);
  if (snakeBody.length > 3) {
    var itemToRemove = snakeBody.shift();
    ctx.clearRect(itemToRemove[0], itemToRemove[1], gridSize, gridSize);
  }
}
```

What happens here is that every time there is a call to drawSnake, the function
adds the new position to the snakeBody array, keeping it in memory. Then, when
the size of the SnakeBody array grows above 3, the SnakeBody array's first
element is removed, and the rectangle is removed. What you should see now is a
little snake moving around, with a tiny body rather than an infinitely-long
line.

![](https://images.thoughtbot.com/new-bamboo/blog/html5-canvas-snake-game/BPCisx9DSTyDMT60uMlI_image_4.jpg)

## Eat food, grow longer

Now we need to add 1 element to the game which is currently not implemented in
any way; we need the food. In the Snake game, little squares of food pop up
around the area, and when the Snake passes over it, he grows longer, hence the
label 'food'. To add this element to the game, we need to do the following:

- Create a method to draw a food square on the canvas, inserted in a random
- location that is not occupied by the Snake's body When the Snake passes over
- that food item, increase the Snake's body length, and place a food square
- somewhere else

We already know how to draw squares, but how do we place them in a random
location, one which is not occupied by the Snake? The former problem is solved
by using the Math library, and the latter by detecting whether the snakeBody
array contains an array of the random point that is suggested for locating the
food square. Here is the code:

```javascript
function makeFoodItem(){
  suggestedPoint = [Math.floor(Math.random()*(canvas.width/gridSize))*gridSize, Math.floor(Math.random()*(canvas.height/gridSize))*gridSize];
  if (snakeBody.some(hasPoint)) {
    makeFoodItem();
  } else {
    ctx.fillStyle = "rgb(10,100,0)";
    ctx.fillRect(suggestedPoint[0], suggestedPoint[1], gridSize, gridSize);
  };
}

function hasPoint(element, index, array) {
  return (element[0] == suggestedPoint[0] &amp;&amp; element[1] == suggestedPoint[1]);
}
```

It looks ugly, it probably is ugly, so I must confess, I'm not a Javascript guru
(that's why I pester Ismael now and then), but I'll explain the logic. First,
before we can do anything, we need to generate a random point in the canvas, an
array of two numbers well within the range of the canvas' width and height, but
also rounded so that the random numbers are divisble by the gridSize, which
happens to be 10.

Secondly, we need to check if the suggestedPoint is already occupied by the
Snake's body. Unfortunately comparing an array of arrays is not a
straightforward procedure in javascript, so I had to create a function called
hasPoint, which using Array.some, will return true if any of the snakeBody
array's arrays directly match with the suggestedPoint array.

If snakeBody already has the suggestedPoint in its collection, then we run the
whole method all over again, and this repeats until the other case occurs, in
which case set the fill color to green, and then draw a square of that color,
with the suggestedPoint's coordinates.

A special note, make sure to move the red fillcolor line to the drawSnake
function, as demonstrated below:

```javascript
function drawSnake() {
  snakeBody.push([currentPosition['x'], currentPosition['y']]);
  ctx.fillStyle = "rgb(200,0,0)";
}
```

If you don't, you'll be scratching your head wondering why your beloved snake
just turned green. Put `makeFoodItem();` right in the IF block for the
canvas-supported initial startup code, and what you should see is a little green
square on the map, awesome. For an added bonus, move your Snake so he eats the
food...

It's gone! but wait, we didn't write any code to remove the green square after
we ate it?

Intentionally, no, unintentionally, yes. The little code which helps to give the
impression of the Snake moving by removing the trailing squares also  clears the
area where the Snake has been, including green squares. How nice is that?

We're close, now we need to make the food reappear in a different place once it
has been snacked on, and we need the Snake to grow in length. First, start by
putting this code in the canvas-supported IF statement block, precisely in this
order:

```javascript
snakeLength = 3;
makeFoodItem();

drawSnake();
```

The `makeFoodItem()` function must come before the drawSnake function, otherwise
the code will break because of the suggestedPoint variable being missing. You'll
also notice that we've defined a snakeLength variable, with the value of 3, the
same value used to determine when to start bumping the last points from the
snakeBody array? You can guess where this is heading, and here is the answer:

```javascript
function drawSnake() {
  snakeBody.push([currentPosition['x'], currentPosition['y']]);
  ctx.fillStyle = "rgb(200,0,0)";
  ctx.fillRect(currentPosition['x'], currentPosition['y'], gridSize, gridSize);
  if (snakeBody.length > snakeLength) {
    var itemToRemove = snakeBody.shift();
    ctx.clearRect(itemToRemove[0], itemToRemove[1], gridSize, gridSize);
  }
  if (currentPosition['x'] == suggestedPoint[0] &amp;&amp; currentPosition['y'] == suggestedPoint[1]) {
    makeFoodItem();
    snakeLength += 1;
  }
}
```

You'll notice 2 changes to the drawSnake method. Firstly, it now refers to the
snakeLength variable instead of just 3, and importantly, the IF statement
comparison of the currentPosition variable with the suggestedPoint variable
allows us to capture when the Snake eats the food, so then we generate the next
food item on the canvas, and we increment the snakeLength variable, which makes
the Snake grow longer. Refresh the browser and see it in action.

![](https://images.thoughtbot.com/new-bamboo/blog/html5-canvas-snake-game/wIGFtH2RTPyWCaGAUnVJ_image_5.jpg)

## Game Over

We're very close to finishing the game, except for one small thing, we haven't
catered for when the Snake bumps into itself, and thus the end game case. Right
now, if the Snake moves over itself, it simply continues its path. What we need
to do here is the following:

- Track when the snake traverses over itself
- End the game once that happens

Thankfully, to deal with No. 1, we've already got a solution at hand:

```javascript
function drawSnake() {
  if (snakeBody.some(hasEatenItself)) {
    gameOver();
    return false;
  }
}

function hasEatenItself(element, index, array) {
  return (element[0] == currentPosition['x'] &amp;&amp; element[1] == currentPosition['y']);
}
```

The `hasEatenItself` function checks if the `currentPosition` point is already
occupied by the Snake's body (i.e. the `snakeBody` array contains the
`currentPosition`), and if it is, it will call a new function called `gameOver`:

```javascript
function gameOver() {
    var score = (snakeLength - 3)*10;
    clearInterval(interval);
    snakeBody = [];
    snakeLength = 3;
    allowPressKeys = false;
    alert("Game Over. Your score was " + score);
    ctx.clearRect(0, 0, canvas.width, canvas.height);
}
```

The gameOver function does a couple of things:

- Calculates the score, and displays it
- Tells the Snake to stop animating (moving)
- Resets the Snake
- flicks a allowPressKeys variable to false (usage explained later)
- Clears the canvas

The allowPressKeys variable is defined in the IF statement canvas-supported
block like this:

```javascript
allowPressKeys = true;
```

and used to disable key press functionality like this:

```javascript
document.onkeydown = function(event) {
  if (!allowPressKeys){
    return null;
  }
}
```

That way, the user cannot move the Snake once the game is over. At this point,
we have effectively replicated the Snake game. That's it. Finito.

## A little spit and polish

Not quite. Yes we could ship it and it would work, but how does the user start
up a new game? or pause it? and what about displaying the score in real time?
We're going to add a few more features before we call this game finished.

Before we add restart and pause functionality, we've got a small usability flaw
in the game. If you press a key that is going in the opposite direction to the
Snake, the game ends since it's effectively trying to go over itself. Logically
this is the correct outcome for the Snake, but when you accidentally go
backwards or hit the keys in the wrong order when trying to execute a sharp
u-turn, then it becomes annoying.

The solution here is to ignore any keystroke going in the opposite direction to
the Snake, like this:

```javascript
switch(keyCode)
{
  case 37:
    if (direction != "right"){
      moveLeft();
    }
    break;

  case 38:
    if (direction != "down"){
      moveUp();
    }
    break;

  case 39:
    if (direction != "left"){
      moveRight();
    }
    break;

  case 40:
    if (direction != "up"){
      moveDown();
    }
    break;
}
```

You simply don't execute the move if the Snake is going in the opposite
direction. Try it now, you'll notice that the Snake continues in its current
direction if you attempt to make it go backwards.

Next, we want to be able to pause the game.

```javascript
function pause(){
  clearInterval(interval);
  allowPressKeys = false;
}
```

This stops the animation of the moving snake, and disables keypress movements,
effectively pausing the game for the user. To resume the game, the reverse
happens:

```javascript
function play(){
  interval = setInterval(moveSnake,100);
  allowPressKeys = true;
}
```

With this functionality isolated, you can now DRY up some of the code in other
places:

```javascript
function gameOver(){
  var score = (snakeLength - 3)*10;
  pause();
  alert("Game Over. Your score was "+ score);
  ctx.clearRect(0,0, canvas.width, canvas.height);
}
```

And we can now create a start function that can be used to initialize a new
game.

```javascript
if (canvas.getContext){
  ctx = canvas.getContext('2d');
  this.gridSize = 10;
  start();
}

function start(){
  ctx.clearRect(0,0, canvas.width, canvas.height);
  this.currentPosition = {'x':50, 'y':50};
  snakeBody = [];
  snakeLength = 3;
  makeFoodItem();
  drawSnake();
  direction = 'right';
  play();
}
```

The start function encapsulates all the methods needs to setup a new game.
However, executing a game whilst another game is in progress will cause an
error; the game will restart, but the snake will start to travel faster and
faster as a result. What we need is a way to remove the existing interval
variable, and then start the game:

```javascript
function restart(){
  pause();
  start();
}
```

You can test this methods using the error console in Safari, or by using
Firebug's javascript console for Firefox.

Now would be a good time to add some buttons to the web page to provide the
user with access to these functions. In terms of context, it would make sense to
have the restart and resume buttons hidden by default, and the pause button
displayed by default. Once the pause button is pressed, it is hidden, and the
other 2 buttons are shown.

```html
<body onload='checkSupported();'>
  <span id='logo'>SNAKE</span>
  <div id='play_menu'>
    <button onclick="pause();document.getElementById('play_menu').style.display='none';document.getElementById('pause_menu').style.display='block';">Pause</button>
  </div>
  <div id='pause_menu'>
    <button onclick="restart();document.getElementById('play_menu').style.display='block';document.getElementById('pause_menu').style.display='none';">Restart</button>
    <button onclick="play();document.getElementById('play_menu').style.display='block';document.getElementById('pause_menu').style.display='none';">Resume</button>
  </div>
```

Also add this css rule for displaying the logo and hiding the pause menu buttons
by default:

```css
#logo {
  font-family: helvetica;
  font-size: 1.4em;
}

#pause_menu {
  display: none;
}
```

We're now able to display context-relevant buttons to the user as they play the
game, oh, and when the game finishes:

```html
<div id='restart_menu'>
  <button onclick="restart();document.getElementById('play_menu').style.display='block';document.getElementById('restart_menu').style.display='none';">Restart</button>
</div>
```

and the css:

```css
#pause_menu, #restart_menu {
  display: none;
}
```

and the Snake js:

```javascript
function gameOver(){
  var score = (snakeLength - 3)*10;
  pause();
  alert("Game Over. Your score was "+ score);
  ctx.clearRect(0,0, canvas.width, canvas.height);
  document.getElementById('play_menu').style.display='none';
  document.getElementById('restart_menu').style.display='block';
}
```

Now when a game ends, you can restart the game with ease. I won't say that this
is the most efficient way of doing this, but it does the job. The final thing to
do is to display the score in real time.

```html
<div id="score_container">
  Score:
  <span id="score">0</span>
</div>
```

The css:

```css
#score_container {
  float: right;
  display: inline;
}
```

The snake js code:

```javascript
function updateScore(){
  var score = (snakeLength - 3)*10
  document.getElementById('score').innerText = score;
}
```

We have a new method for updating the score on the page, and we use this in
two places, the first being the drawSnake function, when the Snake eats the
food:

```javascript
function drawSnake() {
  if (snakeBody.some(hasEatenItself)) {
    gameOver();
    return false;
  }
  snakeBody.push([currentPosition['x'], currentPosition['y']]);
  ctx.fillStyle = "rgb(200,0,0)";
  ctx.fillRect(currentPosition['x'], currentPosition['y'], gridSize, gridSize);
  if (snakeBody.length > snakeLength) {
    var itemToRemove = snakeBody.shift();
    ctx.clearRect(itemToRemove[0], itemToRemove[1], gridSize, gridSize);
  }
  if (currentPosition['x'] == suggestedPoint[0] &amp;&amp; currentPosition['y'] == suggestedPoint[1]) {
    makeFoodItem();
    snakeLength += 1;
    updateScore();
  }
}
```

and when the game is started/restarted:

```javascript
function start(){
  ctx.clearRect(0,0, canvas.width, canvas.height);
  this.currentPosition = {'x':50, 'y':50};
  snakeBody = [];
  snakeLength = 3;
  updateScore();
  makeFoodItem();
  drawSnake();
  direction = 'right';
  play();
}
```

Now, when you play the game, you should see the score updated when you eat food,
and reset whenever you press the restart button:

![](https://images.thoughtbot.com/new-bamboo/blog/html5-canvas-snake-game/6YZ7fnmhSgIhBSXWlMbH_image_6.jpg)

That is it. We have a fully-functioning game of Snake, written purely using
HTML5's canvas tag, some CSS, and some javascript. Want to see what it should
play like? [Try the finished game here][snake-game].

[australia-car-guy]: http://www.abc.net.au/news/stories/2009/12/16/2773292.htm
[new-bamboo-thoughtbot]: https://thoughtbot.com/blog/new-bamboo-joins-thoughtbot-in-london
[snake game]: http://snake.heroku.com
[snake source]: https://github.com/paulbjensen/snake
