The classic game of snake makes a nice weekend project, this tutorial shows the game creates using html5 canvas. You can try the finished game a codepen, or check out the code on github
basic grid render · eamonnmcevoy/snake@54395ca_Contribute to eamonnmcevoy/snake development by creating an account on GitHub._github.com
First step is simple, create an index.html to hold our canvas
index.html
<html><head></head><body><canvas id="game"></canvas><script src="./index.js"></script></body></html>
Now a Grid class to be responsible for rendering our game.
Simple code so far, this sets up our canvas object with a 2D context and renders a 50*50 grid of square that will form the play area of the game.
create grid dataset · eamonnmcevoy/snake@525100e_Contribute to eamonnmcevoy/snake development by creating an account on GitHub._github.com
Before we add our snake object, the Grid class needs to be extended a bit. We will hold the grid state in a 2D array, this code will function as before but allow us to specify a ‘state’ for each cell, and colour it accordingly.
create snake object · eamonnmcevoy/snake@ed6fa32_Contribute to eamonnmcevoy/snake development by creating an account on GitHub._github.com
Time to create our slithery hero, the snake! This class holds an array, parts
, to represent the state of the snake. The update
method will be responsible to update the position of the snake and return an array of cells that require updated on the grid, since we only have one cell for now the code is simple. The getter head
returns a copy of the cell at the head of the snake.
create game object · eamonnmcevoy/snake@03b0de9_Contribute to eamonnmcevoy/snake development by creating an account on GitHub._github.com
In order to get our snake moving we need to create a game loop, responsible for updating the game state and coordinating our objects. All the action takes place in the run
method, on each iteration of the game loop we render the grid, perform updates to the game state, and finally add a short delay (50ms) before running the next iteration.
`while(true)` . ¯\_( ⊙_ʖ⊙ )_/¯
move snake · eamonnmcevoy/snake@2b8a11e_Contribute to eamonnmcevoy/snake development by creating an account on GitHub._github.com
Now we are ready to do something interesting, make the snake move. For this stage we will simply move 1 cell to the right on each update. The Snakeupdate
method is a bit more complex now. To move our snake we will calculate the new head position, the remove the ‘tail’ cell and put it in this new position.
isAlive
tests for collisions with the edge of the board and with other cells on the snake.
Its alive!
directional snake · eamonnmcevoy/snake@b03c629_Contribute to eamonnmcevoy/snake development by creating an account on GitHub._github.com
Now that our snake is on the move, we can start receiving keyboard input to control the direction of travel. The Game class now contains a handler method to process keyboard input, the arrow keys are bound to turn the snake up, down, left, or right. The snake has also been extended with an updatePosition
method to determine the new position.
render optimization · eamonnmcevoy/snake@065c516_Contribute to eamonnmcevoy/snake development by creating an account on GitHub._github.com
There is a fairly bad inefficiency in the rendering of the game grid. On each iteration we redraw every cell, when we really only need to update cells that have changed since the last frame. This a simple change to make, the grid will hold an array of updatedCells
, on calling setPoint
we will push each point on to this array. Now we only need to redraw cells from this array, reducing the work of the render method from 2500 cells per frame to around 2–3, not a bad improvement for 4 lines of code.
generate food · eamonnmcevoy/snake@e7c7001_Contribute to eamonnmcevoy/snake development by creating an account on GitHub._github.com
All this work is making me hungry, time to cook up some lunch for our scaly friend. Every 1 second, if there is no food on the grid, we will add one purple food cell at a random position.
pickup food · eamonnmcevoy/snake@e513f98_Contribute to eamonnmcevoy/snake development by creating an account on GitHub._github.com
The final and most important element of gameplay, when the snake head collides with a food cell the snake should grow. In the main game loop we need to perform a simple check for collision with the food cell, if detected, remove the cell and grow the snake by one. To grow the snake, we add a new cell to the tail, in place of the previous tail position.
track score · eamonnmcevoy/snake@f1cf27b_Contribute to eamonnmcevoy/snake development by creating an account on GitHub._github.com
One final update to finish the game off, when a piece of food is collected, award 1 point. Simply add a score
property to the Game class, increment when food is collected, display the score below the Canvas.
Hope you enjoyed this quick weekend project, if you would like more content like this give a few claps, or comments. Happy coding!