home.

tagged: canvas

Javascript: Animate a sprite in canvas

Let's say we have an image like this: http://www.williammalone.com/articles/create-html5-canvas-javascript-sprite-animation/images/coin-sprite-animation-sprite-sheet.png
 
It has ten mini-images in it. We're going to show the different images in a sequence to create an animation.
 
But first let's load the image:

// First look at this 
// http://www.williammalone.com/articles/create-html5-canvas-javascript-sprite-animation/images/coin-sprite-animation-sprite-sheet.png

var ctx = document.getElementById('canvas').getContext('2d');
var img = new Image();
img.src = 'http://www.williammalone.com/articles/create-html5-canvas-javascript-sprite-animation/images/coin-sprite-animation-sprite-sheet.png';

img.onload = function() {
  var totalNumberOfFrames = 10 // ten images in the image (see the url above)
  var imageFrameNumber = 0 // This is changed to make the sprite animate  
  var widthOfImage = img.width; // find the width of the image
  var heightOfImage = img.height; // find the height of the image
  var widthOfSingleImage = widthOfImage / totalNumberOfFrames; // The width of each image in the spirite
  

We're getting the width and height of the image once it's loaded. And we're getting the width of a single image in our large tile of images (our sprite above). We set a imageFrameNumber which we'll use next.
 
Next we're going to set a interval. When it's run we're going to clear the screen, then update the imageFrameNumber. We're going to make sure it goes from 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 and then back to 0 and 1, 2, 3, 4, 5, 6, 7, 8, 9 etc:

  setInterval(function() {
    ctx.clearRect(0, 0, 400, 400)    
    
    // Changes the sprite we look at    
    imageFrameNumber++; 
    // Change this from 0 to 1 to 2 ... upto 9 and back to 0 again, then 1...
    imageFrameNumber = imageFrameNumber % totalNumberOfFrames; 
    
     ...
    );      
  }, 100)

Next, we're going to draw the image we loaded above. When imageFrameNumber is 0 then we'll print the first sprite, and when it's 1 we'll print the second, etc:

    ctx.drawImage(img, 
      imageFrameNumber * widthOfSingleImage, 0, // x and y - where in the sprite
      widthOfSingleImage, heightOfImage, // width and height
      50, 50, // x and y - where on the screen
      widthOfSingleImage, heightOfImage // width and height
    );   

All our code is:

// First look at this 
// http://www.williammalone.com/articles/create-html5-canvas-javascript-sprite-animation/images/coin-sprite-animation-sprite-sheet.png

var ctx = document.getElementById('canvas').getContext('2d');
var img = new Image();
img.src = 'http://www.williammalone.com/articles/create-html5-canvas-javascript-sprite-animation/images/coin-sprite-animation-sprite-sheet.png';

img.onload = function() {
  var totalNumberOfFrames = 10 // ten images in the image (see the url above)
  var imageFrameNumber = 0 // This is changed to make the sprite animate  
  var widthOfImage = img.width; // find the width of the image
  var heightOfImage = img.height; // find the height of the image
  var widthOfSingleImage = widthOfImage / totalNumberOfFrames; // The width of each image in the spirite
  
  setInterval(function() {
    ctx.clearRect(0, 0, 500, 500)    
    
    imageFrameNumber++; // changes the sprite we look at
    imageFrameNumber = imageFrameNumber % totalNumberOfFrames; // Change this from 0 to 1 to 2 ... upto 9 and back to 0 again, then 1...
    
    ctx.drawImage(img, 
      imageFrameNumber * widthOfSingleImage, 0, // x and y - where in the sprite
      widthOfSingleImage, heightOfImage, // width and height
      50, 50, // x and y - where on the screen
      widthOfSingleImage, heightOfImage // width and height
    );      
  }, 100)  
  
}

javascript canvas


Javascript: Collision detection in canvas

Previously we created a player on the screen and created obstacles:

var canvas = document.querySelector("canvas")
var context = canvas.getContext("2d");
var obstacles = [{width: 30, height: 30, x: canvas.width - 110, y:110}];
var player = {width: 30, height: 30, x: 0, y:100, speedX: 0.0, speedY: 0.0};
var frame = 0

function updateGameArea() {
    frame++
    context.clearRect(0, 0, canvas.width, canvas.height)
  
    // Add a new obstacle
    if(frame % 100 == 0) obstacles.push({width: 30, height: 30, x: canvas.width, y:canvas.height * Math.random(), speedX: 0.0, speedY: 0.0});
    // Render the obstacles
    obstacles.forEach(o => {
      o.x -= 1
      if(o.hit) context.fillStyle = "red"
      context.fillRect(o.x, o.y, o.width, o.height);    
      context.fillStyle = "black"
    })
  
    // Change the player position
    player.x += player.speedX;
    player.y += player.speedY;
    context.fillRect(player.x, player.y, player.width, player.height);

    requestAnimationFrame(updateGameArea);
}

// When the user pressed the array keys change the speed on the player
window.onkeydown = function(event) {
  event.preventDefault() // stop the arrow keys scrolling the page
  if(event.keyCode == 40) { // down
    player.speedY += 1
  } else if(event.keyCode == 38) { // up
    player.speedY -= 1
  } else if(event.keyCode == 39) { // right 
    player.speedX += 1
  } else if(event.keyCode == 37) { // left
    player.speedX -= 1        
  } 
}

// When the use releases the key, stop the speed and thus position movement
window.onkeyup = function(event) {
  event.preventDefault() // stop the arrow keys scrolling the page
  player.speedX = 0
  player.speedY = 0
}

requestAnimationFrame(updateGameArea);

We're going to use a function that detects if a box (somethig with width, height, x and y properties) is touching another:

function hasHit(box1, box2) {
  var box1Right = box1.x + box1.width
  var box1Bottom = box1.y + box1.height  
  var box2Right = box2.x + box2.width
  var box2Bottom = box2.y + box2.height  
  
  if(box1Right > box2.x && box2Right > box1.x && 
    box1Bottom > box2.y && box2Bottom > box1.y) return true;
  else return false;
}

In the update function, we're going to look at all the obstacles, and check that against our player. If collide, we set a 'hit' property on our obstacle object:

obstacles.forEach(o => {
  if (hasHit(player, o)) {
    o.hit = true;
  }
});

And we'll change our code that renders the obstacles, to do something if 'hit' is true:

obstacles.forEach(o => {
  o.x -= 1
  if(o.hit) context.fillStyle = "red"
  context.fillRect(o.x, o.y, o.width, o.height);    
  context.fillStyle = "black"
})

Our full code is:

var canvas = document.querySelector("canvas")
var context = canvas.getContext("2d");
var obstacles = [{width: 30, height: 30, x: canvas.width - 110, y:110}];
var player = {width: 30, height: 30, x: 0, y:100, speedX: 0.0, speedY: 0.0};

var frame = 0
function updateGameArea() {
    frame++
    context.clearRect(0, 0, canvas.width, canvas.height)
  
    // render the obstacles
    if(frame % 100 == 0) obstacles.push({width: 30, height: 30, x: canvas.width, y:canvas.height * Math.random(), speedX: 0.0, speedY: 0.0});
    obstacles.forEach(o => {
      o.x -= 1
      if(o.hit) context.fillStyle = "red"
      context.fillRect(o.x, o.y, o.width, o.height);    
      context.fillStyle = "black"
    })
  
    // change the player
    player.x += player.speedX;
    player.y += player.speedY;
    context.fillRect(player.x, player.y, player.width, player.height);
  
    // collision detection
    obstacles.forEach(o => {
      if ( hasHit(player,o) ) {
        o.hit = true;
      }
    });

    requestAnimationFrame(updateGameArea);
}


function hasHit(box1, box2) {
  var box1Right = box1.x + box1.width
  var box1Bottom = box1.y + box1.height  
  var box2Right = box2.x + box2.width
  var box2Bottom = box2.y + box2.height  
  
  if(box1Right > box2.x && box2Right > box1.x && 
    box1Bottom > box2.y && box2Bottom > box1.y) return true;
  else return false
}

// When the user pressed the array keys change the speed on the player
window.onkeydown = function(event) {
  event.preventDefault() // stop the arrow keys scrolling the page
  if(event.keyCode == 40) { // down
    player.speedY += 1
  } else if(event.keyCode == 38) { // up
    player.speedY -= 1
  } else if(event.keyCode == 39) { // right 
    player.speedX += 1
  } else if(event.keyCode == 37) { // left
    player.speedX -= 1        
  } 
}

// When the use releases the key, stop the speed and thus position movement
window.onkeyup = function(event) {
  event.preventDefault() // stop the arrow keys scrolling the page
  player.speedX = 0
  player.speedY = 0
}

requestAnimationFrame(updateGameArea);

javascript canvas


Javascript: Create game obstacles in canvas

In our previous tutorial on canvas we smoothly moved a player (read: rectangle). We can use the same kind of code to generate obstacles.
 
We're going to have obstacles moving from the left to the right of the screen.
 
First let's create an array with an initial obstacle: var obstacles = [{width: 30, height: 30, x: canvas.width, y:110}].
 
In our update function we'll loop through them all and draw those rectangles. And move the x each frame back to create movement.

function updateGameArea() {
    context.clearRect(0, 0, canvas.width, canvas.height)  
    obstacles.forEach(o => {
      o.x -= 1
      context.fillRect(o.x, o.y, o.width, o.height);      
    })

    requestAnimationFrame(updateGameArea);  
}

We obviously only have one obstacle. Let's now create a new one each time we see 100 frames. A frame is a counter that is incremented on each animation draw.

var frame = 0
function updateGameArea() {
    frame++
    context.clearRect(0, 0, canvas.width, canvas.height)
  
    if(frame % 100 == 0) obstacles.push({width: 30, height: 30, x: canvas.width, y:canvas.height * Math.random()});
  
    obstacles.forEach(o => {
      o.x -= 1
      context.fillRect(o.x, o.y, o.width, o.height);      
    })

    requestAnimationFrame(updateGameArea);  
}

We'll also randomise the y position of the obstacles.
 
Our full code is:

var canvas = document.querySelector("canvas")
var context = canvas.getContext("2d");
var obstacles = [{width: 30, height: 30, x: canvas.width, y:110}];
var frame = 0
function updateGameArea() {
    frame++
    context.clearRect(0, 0, canvas.width, canvas.height)
  
    if(frame % 100 == 0) obstacles.push({width: 30, height: 30, x: canvas.width, y:canvas.height * Math.random(), speedX: 0.0, speedY: 0.0});
  
    obstacles.forEach(o => {
      o.x -= 1
      context.fillRect(o.x, o.y, o.width, o.height);      
    })

    requestAnimationFrame(updateGameArea);  
}

requestAnimationFrame(updateGameArea);


javascript canvas


Javascript: Smoothly move a player in canvas

Previously we learnt how to move a player around a canvas: https://newfivefour.com/javascript-canvas-move-a-player.html

var canvas = document.querySelector("canvas")
var context = canvas.getContext("2d");
var player = {width: 30, height: 30, x: 0, y:110, speedX: 0.0, speedY: 0.0};

function updateGameArea() {
    context.clearRect(0, 0, canvas.width, canvas.height)  
    context.fillRect(player.x, player.y, player.width, player.height);

    requestAnimationFrame(updateGameArea);  
}

window.onkeydown = function(event) {
  event.preventDefault() // stops the button scrolling the page
  if(event.keyCode == 40) { // down
    player.y += 10
  } else if(event.keyCode == 38) { // up
    player.y -= 10    
  } else if(event.keyCode == 39) { // right 
    player.x += 10    
  } else if(event.keyCode == 37) { // left
    player.x -= 10        
  } 
}

requestAnimationFrame(updateGameArea);

But the movement is jerky. We can fix that.
 
We will make our player object take a speedX and speedY property firstly: player = {width: 30, height: 30, x: 0, y:110, speedX: 0.0, speedY: 0.0}; .
 
And in the update function we will change the player x and y by this variable:

function updateGameArea() {
    context.clearRect(0, 0, canvas.width, canvas.height)  
    player.x += player.speedX;
    player.y += player.speedY;
    context.fillRect(player.x, player.y, player.width, player.height);

    requestAnimationFrame(updateGameArea);  
}

All that's left is the onkeyup and down functions that change the speedX and speedY.
 
When the button is pressed down we'll increase the speed. And when it's released we'll completely stop the movement:
 
Here's all the code:

var canvas = document.querySelector("canvas")
var context = canvas.getContext("2d");
player = {width: 30, height: 30, x: 0, y:110, speedX: 0.0, speedY: 0.0};

function updateGameArea() {
    context.clearRect(0, 0, canvas.width, canvas.height)  
    player.x += player.speedX;
    player.y += player.speedY;
    context.fillRect(player.x, player.y, player.width, player.height);

    requestAnimationFrame(updateGameArea);  
}

window.onkeydown = function(event) {
  event.preventDefault() // stop the arrow keys scrolling the page
  if(event.keyCode == 40) { // down
    player.speedY += 1
  } else if(event.keyCode == 38) { // up
    player.speedY -= 1
  } else if(event.keyCode == 39) { // right 
    player.speedX += 1
  } else if(event.keyCode == 37) { // left
    player.speedX -= 1        
  } 
}

window.onkeyup = function(event) {
  event.preventDefault() // stop the arrow keys scrolling the page
  player.speedX = 0
  player.speedY = 0
}

requestAnimationFrame(updateGameArea);


javascript canvas


Javascript: Move a player on the canvas

We're going to create a player. This is a rectangle. We're going to move it around our canvas.
 
First create a HTML file a canvas tag with width and height attributes.
 
Let's start the javascript. Call requestAnimationFrame with a function that loops by calling requestAnimationFrame inside that function.
 
In the function clear the screen each time. Obviously nothing will be printed on the screen at this point.

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

function updateGameArea() {
    context.clearRect(0, 0, canvas.width, canvas.height)  
    requestAnimationFrame(updateGameArea);  
}

requestAnimationFrame(updateGameArea);

For the next iteration we'll create a player object. It will have height and width and an x and a y.
 
In the updateGameArea function we'll use these properties to draw a rectangle to the screen.

var canvas = document.querySelector("canvas")
var context = canvas.getContext("2d");
var player = {width: 30, height: 30, x: 0, y:110};

function updateGameArea() {
    context.clearRect(0, 0, canvas.width, canvas.height)  
    context.fillRect(player.x, player.y, player.width, player.height);

    requestAnimationFrame(updateGameArea);  
}

requestAnimationFrame(updateGameArea);

This now constantly prints a rectangle to the screen.
 
In the next iteration we will use a onkeydown listener to check for the left, right and up and down buttons.
 
When we find those, we will update the player x and y positions and thus move our player.

var canvas = document.querySelector("canvas")
var context = canvas.getContext("2d");
var player = {width: 30, height: 30, x: 0, y:110, speedX: 0.0, speedY: 0.0};

function updateGameArea() {
    context.clearRect(0, 0, canvas.width, canvas.height)  
    context.fillRect(player.x, player.y, player.width, player.height);

    requestAnimationFrame(updateGameArea);  
}

window.onkeydown = function(event) {
  event.preventDefault() // stops the button scrolling the page
  if(event.keyCode == 40) { // down
    player.y += 10
  } else if(event.keyCode == 38) { // up
    player.y -= 10    
  } else if(event.keyCode == 39) { // right 
    player.x += 10    
  } else if(event.keyCode == 37) { // left
    player.x -= 10        
  } 
}

requestAnimationFrame(updateGameArea);

And voila.

javascript canvas

Page 1 of 2
next