Intro to JavaScript for Games:

Building Snake

Why?

- Awesome learning tool

- Challenging

- Fun

- You get to play the games as you build them! (QA is fun)

 

 

Tools

- HTML/CSS/jQuery

- Canvas

- Web sockets

- Libraries

 

 

Examples!

- Tanks

- Tetris

- Dots & Boxes

- Canvas Visualizations

- Magar.io

Tank Arena

-Utilizes web sockets to let people fight against each other

-https://github.com/yusefmarra/Tank-Arena

-http://tank-arena.herokuapp.com/

Dots and Boxes

- Kierston Hill

- jQ html/css

- https://github.com/KierstonHill83/Dots-and-Boxes-Game

Quattro's Revenge

- Johnny Lamb

- Vanilla JS.

- https://github.com/JohnnyLamb/Quatros-Revenge

Tetris

-Charlie Blackstock

-vanilla js / canvas.

-http://blackstc.github.io/tetris/

-https://github.com/blackstc/tetris

Canvas Visualizations

- Ethan Mannette

- https://github.com/Mannette/intro-to-canvas

 

 

Agar.io clone

-Keith Hopkins 

-project to learn to build AIs

-https://github.com/keithhopkins/node-agario-clone

 

Starcraft

http://gloomyson.github.io/StarCraft/

- what!

-possibilities are endless...

 

 

Today:

- we are going to build Snake.

- work together, meet people, have fun.

- clone this repo down: https://github.com/zbunde/Snake

Step 0: Setup

- git clone git@github.com:zbunde/Snake.git

- Every completed step is a branch

- you can get unstuck by checking out that specific branch!

- git checkout step

 

Step 1: HTML

-we need to add a canvas element to our index.html file and give it a width and height.

 

-this is where our game is going to be displayed.

-give the page a heading if you want!

-we need to include our snake.js file also, since this is where all of our code is going to live.

 

<canvas id="canvas" width="600" height="600"></canvas>
<script type="text/javascript" src="snake.js"></script>

Step 1: Code

<head>
<script type="text/javascript" src="snake.js"></script>
</head>

<body>
  <h3> Snake </h3>
  <canvas id="canvas" width="600" height="600"></canvas>
</body>

index.html

 

git checkout step1

-if you get stuck:

Step 2: Draw a border

-let's draw a border around our canvas so we know what we are working on.

-in our snake.js file let's write a function

called drawBorder that does just that.

-first we need to find the canvas and set it to a variable so we can access it.

var canvas = document.getElementById("canvas");

Step 2: Continued

-now that we have a canvas to work with we can set it's context.

-we will use the 2d context for this game, since snake is a 2d game.

-context is what gives us access to all of the canvas drawing functions for 2d.

var canvas = document.getElementById("canvas");
var context = canvas.getContext('2d');

Step 2: Continued

-now that we have context, we can start drawing things on our page!

-we will use the canvas.width and canvas.height to draw a border around the entire canvas.

 


function drawBorder(){
    var canvas = document.getElementById("canvas");
    var context = canvas.getContext('2d');

    context.strokeRect(0,0, canvas.width, canvas.height);
}

Step 2: Continued

-now we just need to call our function once the dom loads.

 

 

 

document.addEventListener("DOMContentLoaded", function() {
  drawBorder();
});

Step 2: Code

- now that we have a border, lets give it some color!

-lets set our context.strokeStyle to any color of your choice!

 

 

 

 

- if you get stuck:

 

 

function drawBorder(){
  var canvas = document.getElementById('canvas');
  var context = canvas.getContext('2d');
     context.strokeStyle = '#E28D05'
     context.strokeRect(0,0, canvas.width, canvas.height);
}
git checkout step2

Step 3: Intervals

- We need to write a function that causes our game to 'tick' so that we can update our movement, check for death, and paint the canvas again.

- This code is going to be a bit complex so let's write a Game function that will hold it.

- I added a color parameter to our drawBorder function to demonstrate an interval.

-We will delete the conditional and count variable, this is to demonstrate how an interval works.

function Game (){
      var count = 0
      var interval = function() {
        count ++
        if(count % 2 == 0){
          drawBorder('green');
        }
        else {
          drawBorder('red')
        }

          setTimeout(function() {
            requestAnimationFrame(interval);
          }, 1000);
    };
    interval();
}
function drawBorder(color){
  var canvas = document.getElementById("canvas");
  var context = canvas.getContext('2d');
    context.strokeStyle = color
    context.lineWidth=10;
    context.strokeRect(0,0, canvas.width, canvas.height);
}
document.addEventListener("DOMContentLoaded", function() {
  Game()
});
git checkout IntervalExample

Step 3: Intervals

We will delete the conditional and count variable, they were just to demo an interval.

-Lower our interval time to 240ms, 1,000ms is REALLY slow for a game.

-Inside of our interval function we need to do the following things(no particular order yet):

  1. Update Snake.

  2. Draw Snake.

  3. Check if it is still alive.

  4. See if it ate food.

  5. Request the next frame.

 

Step 3: Intervals

function Game (){
   var interval = function() {
        drawBorder('orange')
     }
    setTimeout(function() {
           requestAnimationFrame(interval);
        }, 240);
    
    };

    interval();
}
function drawBorder(color){
  var canvas = document.getElementById("canvas");
  var context = canvas.getContext('2d');
    context.strokeStyle = color
    context.lineWidth=10;
    context.strokeRect(0,0, canvas.width, canvas.height);
}

Step 3: Code


document.addEventListener("DOMContentLoaded", function() {
  Game()
  });

function drawBorder(color){
  var canvas = document.getElementById("canvas");
  var context = canvas.getContext('2d');
    context.strokeStyle = color
    context.strokeRect(0,0, canvas.width, canvas.height);
}


function Game (){
   var interval = function() {
        drawBorder('orange')
     }
    setTimeout(function() {
           requestAnimationFrame(interval);
        }, 240);
    
    };

    interval();
}

-if you are stuck

 

git checkout step3

Step 4: Draw a Snake

-We need a length a color and a width.

-Let's setup a pixelSize variable that we can use to draw each piece of our snake.

- Paint the snake with a length of 8 by using a for loop and painting each pixel of the snake.

-we also want to draw a small white line around each piece of the snake to make them more visible.

 

Step 4: Draw a Snake

function drawSnake (){
  var canvas = document.getElementById("canvas");
  var context = canvas.getContext('2d');
  var pixelSize = canvas.width / 25
      for(var i = 0; i < 8; i++) { 
          context.fillStyle = "orange";
          context.fillRect(i*pixelSize, 0, pixelSize, pixelSize);
          context.strokeStyle = "white";
          context.strokeRect(i*pixelSize, 0, pixelSize, pixelSize);
         }
}

- test your function by calling it in your browser console.

Step 4: Continued

- now that we have this function, we need to call it each interval, along with our drawBorder function.

function Game (){
      var interval = function() {
          drawBorder('orange')
          drawSnake();
          setTimeout(function() {
            requestAnimationFrame(interval);
          }, 1000);
    };
    interval();
}

Step 4: Code

-if you are stuck:

git checkout step4
function Game (){
      var interval = function() {
          drawBorder('orange')
          drawSnake();
          setTimeout(function() {
            requestAnimationFrame(interval);
          }, 240);
    };
    interval();
}

function drawSnake (){
  var canvas = document.getElementById("canvas");
  var context = canvas.getContext('2d');
  var pixelSize = canvas.width / 25
      for(var i = 0; i < 8; i++) {
          context.fillStyle = "orange";
          context.fillRect(i*pixelSize, 0, pixelSize, pixelSize);
          context.strokeStyle = "white";
          context.strokeRect(i*pixelSize, 0, pixelSize, pixelSize);
        }
}

Step 5: Movement!

-We need a way to keep track of the X and Y coordinates of our snake and which direction it is going.

- lets create a way to keep track of Snakes inside of our game.

var Snake = function(){
    var self = this
    self.direction = 'right'
    self.snakeArray = []
    self.length = 8;
      for(var i = length; i>=0; i--) {
        self.snakeArray.push({x: i, y:0});
      }

}

Step 5: Continued

-now that we have a snake object let's use it in our Game.

-our snake is going to move so our drawSnake function is brittle. Let's refactor it to take a snake as an argument.

var  Game = function (){
  var self = this
      self.snake = new Snake()
      var interval = function() {
          drawBorder('orange')
          drawSnake(self.snake);
          setTimeout(function() {
            requestAnimationFrame(interval);
          }, 1000);
    };
    interval();
}

Step 5: Continued

- now that we have access to our snake

we can paint each cell in it.

 

function drawSnake (snake){
  var canvas = document.getElementById("canvas");
  var context = canvas.getContext('2d');
  var pixelSize = canvas.width / 25
      for(var i = 0;  i < snake.snakeArray.length; i++) {
          context.fillStyle = "orange";
          context.fillRect(snake.snakeArray[i].x * pixelSize, snake.snakeArray[i].y * pixelSize,
           pixelSize, pixelSize);
          context.strokeStyle = "white";
          context.strokeRect(snake.snakeArray[i].x * pixelSize, snake.snakeArray[i].y * pixelSize,
           pixelSize, pixelSize);
        }

}

Step 5: Continued

- now that we are painting our snake dynamically we can write an updateSnake function that will change the position of the snake each interval.

-we have 4 directions to chose from, so we need a conditional to handle each case:

function updateSnake(snake){
  var noseX = snake.snakeArray[0].x
  var noseY= snake.snakeArray[0].y
     if(snake.direction == "right") noseX++;
     else if(snake.direction == "left") noseX--;
     else if(snake.direction == "up") noseY--;
     else if(snake.direction == "down") noseY++;

}

Step 5: Continued

- we take the tail of our snake and pop it out of the array. we then put it back to the front, giving the appearance of motion on each interval.

function updateSnake(snake){
  var noseX = snake.snakeArray[0].x
  var noseY= snake.snakeArray[0].y
     if(snake.direction == "right") noseX++;
     else if(snake.direction == "left") noseX--;
     else if(snake.direction == "up") noseY--;
     else if(snake.direction == "down") noseY++;

     var tail = snake.snakeArray.pop();
     tail.x = noseX;
     tail.y = noseY;
     snake.snakeArray.unshift(tail);
}

Step 5: Continued

- we need to now call our updateSnake function in our interval!

var  Game = function (){
  var self = this
      self.snake = new Snake()
      var interval = function() {
          drawBorder('orange')
          updateSnake(self.snake)
          drawSnake(self.snake);
          setTimeout(function() {
            requestAnimationFrame(interval);
          }, 240);
    };
    interval();
}

Step 5: Last piece

-we need to make sure to clear our canvas each interval so that we have a fresh canvas to paint on.

-since our drawBorder function happens first we can clear the canvas inside of it.

stuck? git checkout step5
function drawBorder(color){
  var canvas = document.getElementById('canvas');
  var context = canvas.getContext('2d');
    context.clearRect(0, 0, canvas.width, canvas.height);
    context.strokeStyle = color
    context.strokeRect(0, 0, canvas.width, canvas.height);
}

Step 6: Control

-we need to add controls to our snake so we can determine it's direction!

- let's assign our Game to a variable so we can access and change our snakes direction.

-add event listeners to all of the arrow keys that change the snakes direction appropriately.

 

Step 6: Code

document.addEventListener("DOMContentLoaded", function() {
  game = new  Game()
  });
window.addEventListener('keydown', function(key) {
       key.preventDefault();
          if(key.which == "37")
            game.snake.direction = "left"
          else if(key.which == "39")
            game.snake.direction = "right"
          else if(key.which == "38")
            game.snake.direction = "up"
          else if(key.which == "40")
            game.snake.direction = "down"
});

-if you get stuck:

 

git checkout step6

Step 7: Food

-we need to write two functions, one to create a piece of food, and one to draw the food each interval. 

-we need to make sure that the food is within our canvas.

Step 7: Food

function createFood(){
  var pixelSize = canvas.width / 25
    return  food = {
        x: Math.round(Math.random()*(canvas.width-pixelSize)/pixelSize),
        y: Math.round(Math.random()*(canvas.height-pixelSize)/pixelSize),
      };
}
function drawFood(food){
  var canvas = document.getElementById("canvas");
  var context = canvas.getContext('2d')
  var pixelSize = canvas.width / 25
    context.fillStyle = "blue";
    context.fillRect(food.x * pixelSize, food.y * pixelSize, pixelSize, pixelSize);
    context.strokeStyle = "white";
    context.strokeRect(food.x * pixelSize, food.y * pixelSize, pixelSize, pixelSize);
}

Step 7: Continued

-now that we have our functions we need to use them!

var  Game = function (){
  var self = this
      self.snake = new Snake()
      self.food = createFood()
      var interval = function() {
          drawBorder('orange')
          updateSnake(self.snake)
          drawSnake(self.snake);
          drawFood(self.food)
          setTimeout(function() {
            requestAnimationFrame(interval);
          }, 120);
    };
    interval();
}

Step 7: Code

function createFood(){
  var pixelSize = canvas.width / 25
    return  food = {
        x: Math.round(Math.random()*(canvas.width-pixelSize)/pixelSize),
        y: Math.round(Math.random()*(canvas.height-pixelSize)/pixelSize),
      };
}
function drawFood(food){
  var canvas = document.getElementById("canvas");
  var context = canvas.getContext('2d')
  var pixelSize = canvas.width / 25
    context.fillStyle = "blue";
    context.fillRect(food.x * pixelSize, food.y * pixelSize, pixelSize, pixelSize);
    context.strokeStyle = "white";
    context.strokeRect(food.x * pixelSize, food.y * pixelSize, pixelSize, pixelSize);
}

-if you get stuck:

git checkout step7

Step 8: Collisions

-Now that we have food we need to do something when we run into it.

-We will also check to make sure our snake isn't running out of bounds or into itself here.

-console.log('off map') to check if collisions are working!

- add + 1 for off the map right and down.

- this accounts for us measuring from top left of our snake head. 

function checkCollision(snake, food){
  var canvas = document.getElementById("canvas");
  var pixelSize = canvas.width / 25
    /// if we hit our food!
    if(snake.snakeArray[0].x === food.x && snake.snakeArray[0].y === food.y){
    }
    /// off the map left
    if(snake.snakeArray[0].x < 0 ){
    }
    /// off the map up
    if(snake.snakeArray[0].y < 0 ){
    }
    /// off the map down
    if(snake.snakeArray[0].y + 1> 600/pixelSize ){
    }
    /// off the map right
    if(snake.snakeArray[0].x + 1> 600/pixelSize ){
    }
    /// if we hit our own snake body
    for(var i = 1; i < snake.snakeArray.length; i++){
      if(snake.snakeArray[i].x == snake.snakeArray[0].x
         && snake.snakeArray[i].y == snake.snakeArray[i].y){

      }

    }

}

Step 8: Continued

- now that we are checking for collisions we can call it in our interval function.

var  Game = function (){
  var self = this
      self.snake = new Snake()
      self.food = createFood()
      var interval = function() {
          drawBorder('orange');
          updateSnake(self.snake);
          drawSnake(self.snake);
          drawFood(self.food);
          checkCollision(self.snake, self.food)
          setTimeout(function() {
            requestAnimationFrame(interval);
          }, 240);
    };
    interval();
}

-if you get stuck:

git checkout step8

Step 9: Handling Collisions

-now that we are checking for collisions we need to do stuff when they occur.

-food is easy, we need to create a new piece of food and increase our score!

-add a score to our game.

-update our drawBorder function to also draw a score.

-increase score when we eat food!

var  Game = function (){
  var self = this
      self.snake = new Snake()
      self.food = createFood()
      self.score = 0;
      var interval = function() {
          drawBorder('orange', self.score);
          updateSnake(self.snake);
          drawSnake(self.snake);
          drawFood(self.food);
          checkCollision(self.snake, self.food)
          setTimeout(function() {
            requestAnimationFrame(interval);
          }, 240);
    };
    interval();
}
  if(snake.snakeArray[0].x === food.x && snake.snakeArray[0].y === food.y){
        game.food = createFood()
        game.score++
        var tail = {}
        tail.x = game.snake.snakeArray[0].x
        tail.y = game.snake.snakeArray[0].y
        snake.snakeArray.unshift(tail);
    }
function drawBorder(color, score){
  var canvas = document.getElementById("canvas");
  var context = canvas.getContext('2d');
    context.clearRect(0, 0, canvas.width, canvas.height);
    context.font = "30px Arial";
    context.fillText(score, 0, 30)
    context.strokeStyle = color
    context.strokeRect(0,0, canvas.width, canvas.height);
}

-Now we just need to add draw our score on the canvas.

Step 9: Handling Collisions

-now we need to handle what happens when we go off the map or hit another snake.

- let's just use location.reload(); to refresh our page.

 

function checkCollision(snake, food){
  var canvas = document.getElementById("canvas");
  var pixelSize = canvas.width / 25
    /// if we hit our food!
    if(snake.snakeArray[0].x === food.x && snake.snakeArray[0].y === food.y){
        game.food = createFood()
        game.score++
        var tail = {}
        tail.x = game.snake.snakeArray[0].x
        tail.y = game.snake.snakeArray[0].y
        snake.snakeArray.unshift(tail);
      }
    /// off the map left
    if(snake.snakeArray[0].x < 0 ){
      location.reload();
    }
    /// off the map up
    if(snake.snakeArray[0].y < 0 ){
      location.reload();

    }
    /// off the map down
    if(snake.snakeArray[0].y > 600/pixelSize ){
      location.reload();
    }
    /// off the map right
    if(snake.snakeArray[0].x > 600/pixelSize ){
      location.reload();

    }
    /// if we hit our own snake body
    for(var i = 2; i < snake.snakeArray.length; i++){
      if(snake.snakeArray[i].x == snake.snakeArray[0].x && snake.snakeArray[i].y == snake.snakeArray[0].y){
        location.reload();
      }

    }

}

Step 9: Code

- if you are stuck:

git checkout step9

Step 10: Interval

-now that our game is working, let's add the last set of rules.

-each time we consume food, we want the interval speed of the game to increase.

-add a new score property and set it to 240 to begin.

Step 10: Interval


var  Game = function (){
  var self = this
      self.snake = new Snake()
      self.food = createFood()
      self.score = 0;
      self.speed = 240;

      var interval = function() {
          drawBorder('orange', self.score);
          updateSnake(self.snake);
          drawSnake(self.snake);
          drawFood(self.food);
          checkCollision(self.snake, self.food)
          setTimeout(function() {
            requestAnimationFrame(interval);
        }, self.speed);
    };
    interval();
}

Step 10: Interval

-now we just need to update our game speed when we consume food.

-let's also limit it to 30ms so it is still somewhat playable.

Step 10: Interval

    
    if(snake.snakeArray[0].x === food.x && snake.snakeArray[0].y === food.y){
        game.food = createFood()
        game.score++
        if(game.time > 30){
            game.time = game.time - 15
        }
        var tail = {}
        tail.x = game.snake.snakeArray[0].x
        tail.y = game.snake.snakeArray[0].y
        snake.snakeArray.unshift(tail);
      }

Step 11: Computer Player

-lets add another snake that is controlled by an AI.

-we need to make room in our game for another snake, and write some code to control the computer snake.

-we will give our snakes the ability to take a color so that we can see which one is the computer.

-we added the computer as a new Snake, giving it a color of blue and a Y of 10.

Step 11: updateComputer()

var  Game = function (){
  var self = this
      self.snake = new Snake(0, "red")
      self.computer = new Snake(10, "blue")
      self.food = createFood()
      self.score = 0;
      self.speed = 240;

      var interval = function() {
          drawBorder('orange', self.score);
          updateSnake(self.snake);
          updateSnake(self.computer);
          updateComputer(self.snake, self.food, self.computer)
          drawSnake(self.snake);
          drawSnake(self.computer);
          drawFood(self.food);
          checkCollision(self.snake, self.computer, self.food)

          setTimeout(function() {
            requestAnimationFrame(interval);
        }, self.speed);
    };
    interval();
}

Step 11: AI Cont.

- AI's can be very complex but let's try and break down into a bunch of conditionals.

- the next slide is the AI code that determines what direction to go towards the food.

 

 

 

function updateComputer(snake, food, computer){
    if (food.x === computer.snakeArray[0].x) {
        if (food.y > computer.snakeArray[0].y) {
          if (isSafe(snake, computer, 'down')) computer.direction = 'down';
            } else {
          if (isSafe(snake, computer, 'up')) computer.direction = 'up';
        }
      }
      if (food.y === computer.snakeArray[0].y) {
        if (food.x > computer.snakeArray[0].x) {
          if (isSafe(snake, computer, 'right')) computer.direction = 'right';
        } else {
          if (isSafe(snake, computer, 'left')) computer.direction = 'left';
        }
      }
      if (food.y > computer.snakeArray[0].y) {
        if (isSafe(snake, computer, 'down')) computer.direction = 'down';
    } else if (food.y < computer.snakeArray[0].y) {
        if (isSafe(snake, computer, 'up')) computer.direction = 'up';
      }
      if (food.x > computer.snakeArray[0].x) {
        if (isSafe(snake, computer, 'right')) computer.direction = 'right';
    } else if (food.x < computer.snakeArray[0].x) {
        if (isSafe(snake, computer, 'left')) computer.direction = 'left';
      }
}

Step 11: isSafe

- this next slide is the code that determines if the picked direction is somewhat safe.

 

 


function isSafe(snake, computer, dir){
  var snakeCopy = deepCopy(snake.snakeArray);
  var compCopy = deepCopy(computer.snakeArray);
   switch (dir) {
     case 'left':
       for (var i = 0; i < snakeCopy.length/4; i++) {
         compCopy[0].x--;
         if ( checkBodyCollision(compCopy[0], compCopy) || checkBodyCollision(compCopy[0], snakeCopy)) {
           return false;
         }
       }
       return true;
     case 'right':
       for (var i = 0; i < compCopy.length/4; i++) {
         compCopy[0].x++;
         if (checkBodyCollision(compCopy[0], compCopy) || checkBodyCollision(compCopy[0], snakeCopy)) {
           return false;
         }
       }
       return true;
     case 'up':
       for (var i = 0; i < compCopy.length/4; i++) {
         compCopy[0].y--;
         if (checkBodyCollision(compCopy[0], compCopy) || checkBodyCollision(compCopy[0], snakeCopy)) {
           return false;
         }
       }
       return true;
     case 'down':
       for (var i = 0; i < compCopy.length/4; i++) {
         compCopy[0].y++;
         if (checkBodyCollision(compCopy[0], compCopy) || checkBodyCollision(compCopy[0], snakeCopy)) {
           return false;
         }
       }
       return true;
   }
}

Step 11: AI Helpers

- the functions on the next slide are used by our AI to help make decisions.

 

 

Step 11: AI Helper Code


function checkBodyCollision(head, array) {
  for(var i = 1; i < array.length; i++){
    if(array[i].x == head.x && array[i].y == head.y){
      return true;
    }
  }
  return false;
}

function deepCopy (arr) {
    var out = [];
    for (var i = 0, len = arr.length; i < len; i++) {
        var item = arr[i];
        var obj = {};
        for (var k in item) {
            obj[k] = item[k];
        }
        out.push(obj);
    }
    return out;
}

Step 11: Rework checkCollison()

-now that we have another snake on our canvas we need to account for that in our checkCollision function.

- add conditions to check for the computer leaving the map, and add conditions for the snakes hitting each other.

 

function checkCollision(snake, computer, food){
  var canvas = document.getElementById("canvas");
  var context = canvas.getContext('2d')

  var pixelSize = canvas.width / 25
        /// If we run into the computer.

        for(i=0; i< computer.snakeArray.length; i++){
            if(snake.snakeArray[0].x === computer.snakeArray[i].x && snake.snakeArray[0].y === computer.snakeArray[i].y){
                 alert("You lose!")
                 location.reload()
            }
        }

        /// If the computer runs into us
        for(i=0; i< snake.snakeArray.length; i++){
            if(computer.snakeArray[0].x === snake.snakeArray[i].x && computer.snakeArray[0].y === snake.snakeArray[i].y){
                context.clearRect(0, 0, canvas.width, canvas.height);
                  alert("You win!");
                  location.reload()
            }
        }

        ///  If the computer hits the food.
        if(computer.snakeArray[0].x === food.x && computer.snakeArray[0].y === food.y){
            game.food = createFood()
            game.score--
            if(game.speed > 30){
                game.speed = game.speed - 15
            }
            var tail = {}
            tail.x = computer.snakeArray[0].x
            tail.y = computer.snakeArray[0].y
            computer.snakeArray.unshift(tail);
          }
        /// if we hit our food!
        if(snake.snakeArray[0].x === food.x && snake.snakeArray[0].y === food.y){
            game.food = createFood()
            game.score++
            if(game.speed > 30){
                game.speed = game.speed - 15
            }
            var tail = {}
            tail.x = game.snake.snakeArray[0].x
            tail.y = game.snake.snakeArray[0].y
            snake.snakeArray.unshift(tail);
          }
        /// off the map left
        if(snake.snakeArray[0].x < 0 ){
            alert("You lose!");
            location.reload();
        }
        /// Computer off the map left
        if(computer.snakeArray[0].x < 0 ){
            alert("You win!");
            location.reload();
        }
        /// off the map up
        if(snake.snakeArray[0].y < 0 ){
            alert("You lose!");
            location.reload();
        }
        /// Computer off the map up
        if(computer.snakeArray[0].y < 0 ){
            alert("You win!");
            location.reload();
        }
        /// off the map down
        if(snake.snakeArray[0].y + 1 > 600/pixelSize ){
            alert("Computer wins!");
            location.reload();
        }
        /// Computer off the map down
        if(computer.snakeArray[0].y + 1 > 600/pixelSize ){
            alert("You win!");
            location.reload();
        }

        /// off the map right
        if(snake.snakeArray[0].x + 1 > 600/pixelSize ){
            alert("You lose!");
            location.reload();
        }
        /// Computer off the map right
        if(computer.snakeArray[0].x + 1 > 600/pixelSize ){
            alert("You win!");
            location.reload();
        }
        /// if we hit our own snake body
        for(var i = 2; i < snake.snakeArray.length; i++){
          if(snake.snakeArray[i].x == snake.snakeArray[0].x && snake.snakeArray[i].y == snake.snakeArray[0].y){
              alert("You lose!");
              location.reload();
          }
        }
          /// if computer hits it's own body
          for(var i = 2; i < computer.snakeArray.length; i++){
            if(computer.snakeArray[i].x == computer.snakeArray[0].x && computer.snakeArray[i].y == computer.snakeArray[0].y){
                alert("You win!");
                location.reload();
            }
        }

}

Step 11: Code:

git checkout step11

- if you are stuck:

Step 12: Refactor

- have fun ;)

Game Libraries

- https://html5gameengine.com/

- http://phaser.io/

- https://www.scirra.com/ (Construct 2)

- http://threejs.org/

Next Steps

- write an AI to play Snake

- refactor this code!

- build some other games.

- utilize some of the libraries mentioned.

- build a multiplayer game with websockets.

 

 

Thank you!

- twitter: @zbunde

- github: https://github.com/zbunde

Resources

JS for Games

By Zach Klabunde

JS for Games

  • 726