Create A Classic Snake Game Using HTML5 Canvas in 10 Simple Steps

snakegame.png
 

Introduction

 
These days I'm working on HTML5, so I decided to make some examples using the HTML5 Canvas. The Canvas is one of the best features of HTML5 and you can create beautiful designs using it. In this article, I have tried to make a very old and classy game example that we played many times in our childhood. We used the HTML5 Canvas and a little jQuery to create our "Classic Snake Game".
 
Step 1
 
Create a canvas in your application's body and provide its size, whatever you want. Now, here we create a canvas with 600px width and 600px height:
  1. <canvas id="drawCanvas" width="600" height="600"></canvas>  
Step 2
 
In the head section we need to write our jQuery code in a <script> tag. So, now declare some variables for our canvas that we need in our code
  1. var drawCanvas = $("#drawCanvas")[0];    
  2. var context = drawCanvas.getContext("2d");    
  3. var width = $("#drawCanvas").width();    
  4. var height = $("#drawCanvas").height();     
Step 3
 
Now we declare some variables inside our start() method. For some easy control you can save the width of a cell into a variable:
  1. var cell_width = 15;  
  2. var defaultRun;  
  3. var snake_food;  
  4. var userscore;  
Now, to create a snake we need to define an array of cells:
  1. var mySnakeArray;
Now to start our game we need a function that helps us to run our game:
  1. function start()  
Set the default direction of the snake to go to the right:
  1. defaultRun = "right";  
To create our snake's food we need to create a function:
  1. createFood();  
And also we need to display our score so we can define a variable for it:
  1. userscore = 0;
To move our snake we can use a timer that will trigger the paintSnake method every 70ms: 
  1. if (typeof game_loop != "undefined") clearInterval(game_loop);  
  2. game_loop = setInterval(paintSnake, 70);  
Step 4
 
Now its time to create our Snake using createSnake() method. In this method, we also define the size of our snake and use an empty array to start:
  1. function createSnake() {  
  2.      var snakeSize = 6;  
  3.      mySnakeArray = [];  
  4.      for (var m = 0; m<snakeSize-1;m++) {   
This line will create a horizontal snake starting from the middle left. You can change its position by giving the value of x or y:
  1. mySnakeArray.push({ x: 0, y: 20 });  
Step 5
 
Now its time to create some food for our little hungry snake. Here, we used some mathematical functions that will create a cell with x/y between 0-44 because there are 45(450/10) positions across the rows and columns:
  1. function createFood() {  
  2.     snake_food = {  
  3.         x: Math.round(Math.random() * (width - cell_width) / cell_width),  
  4.         y: Math.round(Math.random() * (height - cell_width) / cell_width),  
  5.     };  
  6.  }  
Step 6
 
After creating our snake we need a paintSnake() method  that paints our snake. We need to paint the Background on every frame to avoid the snake trail:
  1. function paintSnake()  
First we need to paint our canvas:
  1. context.fillStyle = "#c0f0aa";  
  2. context.fillRect(0, 0, width, height);  
  3. context.strokeStyle = "0000ff";  
  4. context.strokeRect(0, 0, width, height);  
Now we need to move our snake. Here, we use two variables that will pop out the last cell and it will place in front of the head cell:
  1. var pop_x = mySnakeArray[0].x;  
  2. var pop_y = mySnakeArray[0].y;  
These are the positions of the head cell. We need to increment it to get the new head position of our snake. Now add some proper direction based moment:
  1. if (defaultRun == "right") pop_x++;  
  2. else if (defaultRun == "left") pop_x--;  
  3. else if (defaultRun == "down") pop_y++;  
  4. else if (defaultRun == "up") pop_y--;  
Its time to add the game so it will restart our game if our snake hits the wall. Also add the body collision code so that if our snake's head bumps into the body then our game will restart:
  1. if (pop_x == -1 || pop_x == width / cell_width || pop_y == -1 || pop_y == height / cell_width || check_collision(pop_x, pop_y, mySnakeArray)) {  
The start() method will restart our game and return helps to organize our code:
  1.      start();  
  2.      return;  
  3. }  
Step 7
 
Now we need to write some code so that our little hungry snake will eat his food. The logic is very simple if the new head position matches with the food then create a new head instead of moving the snake's tail:
  1. if (pop_x == snake_food.x && pop_y == snake_food.y) {  
  2.      var snake_tail = { x: pop_x, y: pop_y };  
  3.      userscore++;  
  4.      createFood();    //It will create our snakes food.  
  5. }  
  6. else {  
  7.     var snake_tail = mySnakeArray.pop();  
  8.     snake_tail.x = pop_x; snake_tail.y = pop_y;  
  9. }  
Finally our little hungry snake is able to eat his food. Now we need to return the snake's tail to the first cell:
  1. mySnakeArray.unshift(snake_tail);  
If you remember, we declared our cell width; we now paint a 15px wide cell using "paintCell(k.x, k.y)". After that we will paint the food & score both:
  1. paintCell(snake_food.x, snake_food.y);                 
  2. var score_text = "Score: " + userscore;  
  3. context.fillText(score_text, width-50, 20);  
Step 8:
 
Now create a generic function that will paint cells:
  1. function paintCell(x, y) {  
  2.      context.fillStyle = "orange";  
  3.      context.fillRect(x * cell_width, y * cell_width, cell_width, cell_width);  
  4.      context.strokeStyle = "red";  
  5.      context.strokeRect(x * cell_width, y * cell_width, cell_width, cell_width);  
  6.  }  
Step 9
 
This is a very important method that will check if the given x/y coordinates exist already in an array of cells or not.
  1. function check_collision(x, y, array) {  
  2.     for (var i = 0; i < array.length; i++) {  
  3.         if (array[i].x == x && aIntroductionrray[i].y == y)  
  4.             return true;  
  5.     }  
  6.     return false;  
  7. }  
Step 10:
 
In this final step we will add the keyboard controls so that we can control our little snake from our keyboard arrow keys.
  1. $(document).keydown(function (e) {  
  2.       var keyInput = e.which;  
We will add another clause to prevent reverse gear:
  1. if (keyInput == "40" && defaultRun != "up") defaultRun = "down";  
  2. else if (keyInput == "39" && defaultRun != "left") defaultRun = "right";  
  3. else if (keyInput == "38" && defaultRun != "down") defaultRun = "up";  
  4. else if (keyInput == "37" && defaultRun != "right") defaultRun = "left";  
We have created our snake game in just 10 simple steps and now its ready to play. I'm providing the complete code below or you can also download the code from the link above.
  1. <%@ Page Language="C#" AutoEventWireup="true" CodeFile="snake.aspx.cs" Inherits="snake" %>  
  2.    
  3. <!DOCTYPE html>  
  4.    
  5. <html xmlns="http://www.w3.org/1999/xhtml">  
  6. <head runat="server">  
  7.     <title></title>  
  8.     <style type="text/css">  
  9.         body {  
  10.             margin: 0 auto;  
  11.             padding : 0;  
  12.         }  
  13.     </style>  
  14.     <!-- Jquery -->  
  15.     <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript"></script>  
  16.     <script>  
  17.         $(document).ready(function () {  
  18.             //Canvas stuff  
  19.             var drawCanvas = $("#drawCanvas")[0];  
  20.             var context = drawCanvas.getContext("2d");  
  21.             var width = $("#drawCanvas").width();  
  22.             var height = $("#drawCanvas").height();  
  23.    
  24.             var cell_width = 15;  
  25.             var defaultRun;  
  26.             var snake_food;  
  27.             var userscore;  
  28.             var mySnakeArray;  
  29.              
  30.            function start() {  
  31.                 defaultRun = "right";  
  32.                 createSnake();  
  33.                 createFood();  
  34.                 userscore = 0;  
  35.                  
  36.                 if (typeof game_loop != "undefined") clearInterval(game_loop);  
  37.                 game_loop = setInterval(paintSnake, 70);  
  38.             }  
  39.             start();  
  40.    
  41.            function createSnake() {  
  42.                 var snakeSize = 6;  
  43.                 mySnakeArray = [];  
  44.                 for (var m = 0; m<snakeSize-1;m++) {  
  45.                     mySnakeArray.push({ x: 0, y: 20 });  
  46.                 }  
  47.             }  
  48.    
  49.             function createFood() {  
  50.                 snake_food = {  Introduction
  51.                     x: Math.round(Math.random() * (width - cell_width) / cell_width),  
  52.                     y: Math.round(Math.random() * (height - cell_width) / cell_width),  
  53.                 };  
  54.              }  
  55.    
  56.             function paintSnake() {  
  57.                 context.fillStyle = "#c0f0aa";  
  58.                 context.fillRect(0, 0, width, height);  
  59.                 context.strokeStyle = "0000ff";  
  60.                 context.strokeRect(0, 0, width, height);  
  61.    
  62.                 var pop_x = mySnakeArray[0].x;  
  63.                 var pop_y = mySnakeArray[0].y;  
  64.    
  65.                 if (defaultRun == "right") pop_x++;  
  66.                 else if (defaultRun == "left") pop_x--;  
  67.                 else if (defaultRun == "down") pop_y++;  
  68.                 else if (defaultRun == "up") pop_y--;  
  69.                  
  70.    
  71.                  if (pop_x == -1 || pop_x == width / cell_width || pop_y == -1 || pop_y == height / cell_width || check_collision(pop_x, pop_y, mySnakeArray)) {  
  72.                      start();  
  73.                      return;  
  74.                 }  
  75.    
  76.                  if (pop_x == snake_food.x && pop_y == snake_food.y) {  
  77.                     var snake_tail = { x: pop_x, y: pop_y };  
  78.                     userscore++;  
  79.                      createFood();  
  80.                 }  
  81.                 else {  
  82.                     var snake_tail = mySnakeArray.pop();  
  83.                     snake_tail.x = pop_x; snake_tail.y = pop_y;  
  84.                 }  
  85.    
  86.                 mySnakeArray.unshift(snake_tail);  
  87.    
  88.                 for (var i = 0; i < mySnakeArray.length; i++) {  
  89.                     var k = mySnakeArray[i];  
  90.                   
  91.                     paintCell(k.x, k.y);  
  92.                 }  
  93.    
  94.                  
  95.                 paintCell(snake_food.x, snake_food.y);  
  96.                  
  97.                 var score_text = "Score: " + userscore;  
  98.                 context.fillText(score_text, width-50, 20);  
  99.             }  
  100.    
  101.            function paintCell(x, y) {  
  102.                 context.fillStyle = "orange";  
  103.                 context.fillRect(x * cell_width, y * cell_width, cell_width, cell_width);  
  104.                 context.strokeStyle = "red";  
  105.                 context.strokeRect(x * cell_width, y * cell_width, cell_width, cell_width);  
  106.             }  
  107.    
  108.             function check_collision(x, y, array) {  
  109.                 for (var i = 0; i < array.length; i++) {  
  110.                     if (array[i].x == x && array[i].y == y)  
  111.                         return true;  
  112.                 }  
  113.                 return false;  
  114.             }  
  115.    
  116.           $(document).keydown(function (e) {  
  117.                 var keyInput = e.which;  
  118.                 if (keyInput == "40" && defaultRun != "up") defaultRun = "down";  
  119.                 else if (keyInput == "39" && defaultRun != "left") defaultRun = "right";  
  120.                 else if (keyInput == "38" && defaultRun != "down") defaultRun = "up";  
  121.                 else if (keyInput == "37" && defaultRun != "right") defaultRun = "left";  
  122.             })  
  123.         })  
  124.     </script>  
  125. </head>  
  126. <body>  
  127.     <form id="form1" runat="server">  
  128.         <div>  
  129.              <canvas id="drawCanvas" width="550" height="600"></canvas>  
  130.    
  131.         </div>  
  132.     </form>  
  133. </body>  
  134. </html>


Similar Articles