JavaScript Snake tutorial
last modified July 7, 2020
JavaScript Snake tutorial shows how to create a Snake game in JavaScript. The images and sources are available at the author's Github JavaScript-Snake-Game repository.
Snake game
Snake is an older classic video game which was first created in late 70s. Later it was brought to PCs. In this game the player controls a snake. The objective is to eat as many apples as possible. Each time the snake eats an apple, its body grows. The snake must avoid the walls and its own body. This game is sometimes called Nibbles.
HTML5 Canvas
HTML5 canvas element provides a resolution-dependent bitmap area, which can be used for rendering graphs, game graphics, art, or other visual images on the fly. In simple terms, canvas is a new element in HTML5, which allows you to draw graphics using JavaScript. Canvas brings animations to web pages without the need of plugins like Flash, Silverlight, or Java.
JavaScript Snake code example
The size of each of the joints of a snake is 10 px. The snake is controlled with the cursor keys. Initially, the snake has three joints. If the game is finished, the "Game Over" message is displayed in the middle of the canvas.
<!DOCTYPE html> <html> <head> <title>JavaScript Snake game</title> <style> canvas {background: black} </style> <script src="snake.js"></script> </head> <body onload="init();"> <canvas id="myCanvas" width="300" height="300"> </canvas> </body> </html>
This is the HTML source. We put the JavaScript source in the snake.js
file.
<canvas id="myCanvas" width="300" height="300"> </canvas>
We create a canvas object. It is a rendering area for our game.
// JavaScript Snake example // Author Jan Bodnar // http://zetcode.com/javascript/snake/ var canvas; var ctx; var head; var apple; var ball; var dots; var apple_x; var apple_y; var leftDirection = false; var rightDirection = true; var upDirection = false; var downDirection = false; var inGame = true; const DOT_SIZE = 10; const ALL_DOTS = 900; const MAX_RAND = 29; const DELAY = 140; const C_HEIGHT = 300; const C_WIDTH = 300; const LEFT_KEY = 37; const RIGHT_KEY = 39; const UP_KEY = 38; const DOWN_KEY = 40; var x = new Array(ALL_DOTS); var y = new Array(ALL_DOTS); function init() { canvas = document.getElementById('myCanvas'); ctx = canvas.getContext('2d'); loadImages(); createSnake(); locateApple(); setTimeout("gameCycle()", DELAY); } function loadImages() { head = new Image(); head.src = 'head.png'; ball = new Image(); ball.src = 'dot.png'; apple = new Image(); apple.src = 'apple.png'; } function createSnake() { dots = 3; for (var z = 0; z < dots; z++) { x[z] = 50 - z * 10; y[z] = 50; } } function checkApple() { if ((x[0] == apple_x) && (y[0] == apple_y)) { dots++; locateApple(); } } function doDrawing() { ctx.clearRect(0, 0, C_WIDTH, C_HEIGHT); if (inGame) { ctx.drawImage(apple, apple_x, apple_y); for (var z = 0; z < dots; z++) { if (z == 0) { ctx.drawImage(head, x[z], y[z]); } else { ctx.drawImage(ball, x[z], y[z]); } } } else { gameOver(); } } function gameOver() { ctx.fillStyle = 'white'; ctx.textBaseline = 'middle'; ctx.textAlign = 'center'; ctx.font = 'normal bold 18px serif'; ctx.fillText('Game over', C_WIDTH/2, C_HEIGHT/2); } function checkApple() { if ((x[0] == apple_x) && (y[0] == apple_y)) { dots++; locateApple(); } } function move() { for (var z = dots; z > 0; z--) { x[z] = x[(z - 1)]; y[z] = y[(z - 1)]; } if (leftDirection) { x[0] -= DOT_SIZE; } if (rightDirection) { x[0] += DOT_SIZE; } if (upDirection) { y[0] -= DOT_SIZE; } if (downDirection) { y[0] += DOT_SIZE; } } function checkCollision() { for (var z = dots; z > 0; z--) { if ((z > 4) && (x[0] == x[z]) && (y[0] == y[z])) { inGame = false; } } if (y[0] >= C_HEIGHT) { inGame = false; } if (y[0] < 0) { inGame = false; } if (x[0] >= C_WIDTH) { inGame = false; } if (x[0] < 0) { inGame = false; } } function locateApple() { var r = Math.floor(Math.random() * MAX_RAND); apple_x = r * DOT_SIZE; r = Math.floor(Math.random() * MAX_RAND); apple_y = r * DOT_SIZE; } function gameCycle() { if (inGame) { checkApple(); checkCollision(); move(); doDrawing(); setTimeout("gameCycle()", DELAY); } } onkeydown = function(e) { var key = e.keyCode; if ((key == LEFT_KEY) && (!rightDirection)) { leftDirection = true; upDirection = false; downDirection = false; } if ((key == RIGHT_KEY) && (!leftDirection)) { rightDirection = true; upDirection = false; downDirection = false; } if ((key == UP_KEY) && (!downDirection)) { upDirection = true; rightDirection = false; leftDirection = false; } if ((key == DOWN_KEY) && (!upDirection)) { downDirection = true; rightDirection = false; leftDirection = false; } };
This is the JavaScript Snake source.
const DOT_SIZE = 10; const ALL_DOTS = 900; const MAX_RAND = 29; const DELAY = 140; const C_HEIGHT = 300; const C_WIDTH = 300;
DOT_SIZE
is the size of the apple and the dot of
the snake. ALL_DOTS
constant defines the maximum number
of possible dots on the canvas (900 = 300*300/10*10). MAX_RAND
constant is used to calculate a random position for an apple.
DELAY
constant determines the speed of the game. C_HEIGHT
and C_WIDTH
constants store the size of the canvas.
const LEFT_KEY = 37; const RIGHT_KEY = 39; const UP_KEY = 38; const DOWN_KEY = 40;
These constants store the values of arrow keys. They are used for better readability.
var x = new Array(ALL_DOTS); var y = new Array(ALL_DOTS);
These two arrays store the x and y coordinates of all joints of a snake.
function init() { canvas = document.getElementById('myCanvas'); ctx = canvas.getContext('2d'); loadImages(); createSnake(); locateApple(); setTimeout("gameCycle()", DELAY); }
The init()
function gets the reference to the canvas object and its
context. The loadImages()
, createSnake()
, and locateApple()
functions are called to perform specific tasks. The setTimeout()
starts the
animation.
function loadImages() { head = new Image(); head.src = 'head.png'; ball = new Image(); ball.src = 'dot.png'; apple = new Image(); apple.src = 'apple.png'; }
In the loadImages()
function we load three images for the game.
function createSnake() { dots = 3; for (var z = 0; z < dots; z++) { x[z] = 50 - z * 10; y[z] = 50; } }
In the createSnake()
function we create the snake object. At the
start, it has three joints.
function checkApple() { if ((x[0] == apple_x) && (y[0] == apple_y)) { dots++; locateApple(); } }
If the head collides with the apple, we increase the number of joints of the snake.
We call the locateApple()
method which randomly positions a new apple object.
function move() { ...
In the move()
method we have the key algorithm of the game. In order to
understand it, look at how the snake is moving. We control the head of the snake.
We can change its direction with the cursor keys.
The rest of the joints move one position up the chain. The second joint
moves where the first was, the third joint where the second was etc.
for (var z = dots; z > 0; z--) { x[z] = x[(z - 1)]; y[z] = y[(z - 1)]; }
The for loop moves the joints of a snake up the chain.
if (leftDirection) { x[0] -= DOT_SIZE; }
This line moves the head to the left.
function checkCollision() { ...
In the checkCollision()
method, we determine if
the snake has hit itself or one of the borders.
for (var z = dots; z > 0; z--) { if ((z > 4) && (x[0] == x[z]) && (y[0] == y[z])) { inGame = false; } }
If the snake hits one of its joints with its head, the game is over.
if (y[0] >= C_HEIGHT) { inGame = false; }
The game is finished if the snake hits the bottom of the canvas.
function locateApple() { var r = Math.floor(Math.random() * MAX_RAND); apple_x = r * DOT_SIZE; r = Math.floor(Math.random() * MAX_RAND); apple_y = r * DOT_SIZE; }
The locateApple()
randomly selects x and y coordinates
for the apple object. The apple_x
and apple_y
are the coordinates of the uppler-left point of the apple
image.
function gameCycle() { if (inGame) { checkApple(); checkCollision(); move(); doDrawing(); setTimeout("gameCycle()", DELAY); } }
The gameCycle()
function forms a game cycle. Provided that
the game has not finished, we perform collision detection, do movement and
drawing. The setTimeout()
function calls recursively the
gameCycle()
function.
if ((key == LEFT_KEY) && (!rightDirection)) { leftDirection = true; upDirection = false; downDirection = false; }
If we hit the left cursor key, we set the leftDirection
variable to true.
This variable is used in the move()
function to change the coordinates of
the snake object. Notice also that when the snake is heading to the right, we cannot
immediately turn to the left.

This was JavaScript Snake game.
List all JavaScript tutorials.