HTML5 canvas: create animated character with sprite sheets


Today, we learn how to create animated character with sprite sheets, json and javascript.

We use the below sprites sheet:

https://raw.githubusercontent.com/mozilla/BrowserQuest/master/client/img/1/clotharmor.png

character sprite sheets
Copyright: Mozilla & Github

And json data: https://raw.githubusercontent.com/mozilla/BrowserQuest/master/client/sprites/clotharmor.json
Copyright: Mozilla & Github

{
	"id": "clotharmor",
	"width": 32,
	"height": 32,
	"animations": {
		"atk_right": {
			"length": 5,
			"row": 0
		},
		"walk_right": {
			"length": 4,
			"row": 1
		},
		"idle_right": {
			"length": 2,
			"row": 2
		},
		"atk_up": {
			"length": 5,
			"row": 3
		},
		"walk_up": {
			"length": 4,
			"row": 4
		},
		"idle_up": {
			"length": 2,
			"row": 5
		},
		"atk_down": {
			"length": 5,
			"row": 6
		},
		"walk_down": {
			"length": 4,
			"row": 7
		},
		"idle_down": {
			"length": 2,
			"row": 8
		}
	},
	"offset_x": -8,
	"offset_y": -12
}

First step: analysis the structure of the json file and the sprite sheets

Seeing the json file, we can determine the size of a sprite sheet is 32x32px and there are 9 states of character:

  • atk_right: attack right
  • walk_right: walk right
  • idle_right: idle right
  • atk_up: attack up
  • walk_up: walk up
  • idle_up: idle up
  • atk_down: attack down
  • walk_down: walk down
  • idle_down: idle down

Here are the sprite sheets: (scale 200%)
character sheet

We test for the walk right state:
HTML

<canvas id="mycanvas" width="32" height="32"></canvas>

Javascript

var canvas = document.getElementById('mycanvas'),
    ctx = canvas.getContext('2d'),
    image = new Image(),
    json = {};//data json
var state = 'walk_right';//9 states
jQuery.getJSON("https://raw.githubusercontent.com/mozilla/BrowserQuest/master/client/sprites/clotharmor.json", function (data) {
    json = data.animations[state]; // length, row
});
var numr = 1;//total images
var n = 0;//number of images loaded
image.onload = function () {
    n += 1;
}
image.src = 'https://raw.githubusercontent.com/mozilla/BrowserQuest/master/client/img/1/clotharmor.png';
var i = 0;
//speed:  milisecond per sprite sheet 
var Speed = 200;
//frames per second
var fps = 30;
function demo() {
	//wait for load json and images
    if (n == numr && json.length) {
            ctx.drawImage(image, (i++) * 32, json.row * 32, 32, 32, 0, 0, 32, 32);
            if (i == json.length) i = 0;
            timestart = (new Date()).getTime();
    }
}
setInterval(demo, 1000 / fps);

Result:

However, the sprites are overlapping, we must clear the previous sprite by using clearRec function.

ctx.clearRect(0, 0, canvas.width, canvas.height);

We receive the result below:

However, the character’s movement speed is too fast, we need to control the speed using time:

var canvas = document.getElementById('mycanvas'),
    ctx = canvas.getContext('2d'),
    image = new Image(),
    json = {};//data json
var state = 'walk_right';//9 states
jQuery.getJSON("https://raw.githubusercontent.com/mozilla/BrowserQuest/master/client/sprites/clotharmor.json", function (data) {
    json = data.animations[state]; // length, row
});
var numr = 1;//total images
var n = 0;//number of images loaded
image.onload = function () {
    n += 1;
}
image.src = 'https://raw.githubusercontent.com/mozilla/BrowserQuest/master/client/img/1/clotharmor.png';
var i = 0;
var timestart = (new Date()).getTime();
//speed:  milisecond per sprite sheet 
var Speed = 200;
//frames per second
var fps = 30;
function demo() {
	//wait for load json and images
    if (n == numr && json.length) {
        var delta = (new Date()).getTime() - timestart;
        if (delta >= Speed) {
            ctx.clearRect(0, 0, canvas.width, canvas.height);
            ctx.drawImage(image, (i++) * 32, json.row * 32, 32, 32, 0, 0, 32, 32);
            if (i == json.length) i = 0;
            timestart = (new Date()).getTime();
        }
    }
}
setInterval(demo, 1000 / fps);

We receive the result below:

Try it yourself:
https://jsfiddle.net/sans_amour/cp11LL78/2/

Leave a Reply