HTML5 Platform Game

Created on December 28, 2018

In this course we'll be showing you how to create an HTML5 Platform Game. In this course we'll be walking through step-by-step on how to draw an intro screen, draw the character to the screen, capture user input, collision detection, and so much more.

Let's get started in the next video where we'll show you how to add a canvas and draw your intro screen. This course is broken down into 9 different section which include:

  • Drawing the Canvas and Intro Screen
  • Capturing Input & Game Loop
  • Character Movement
  • Character Jumping and Platforms
  • Collision Detection
  • Animation Loop, Walls, and Ceiling
  • Adding a Goal & Resetting the Game
  • Images and Platform Styles
  • Adding Backgrounds and Wrapping Up

Drawing the Canvas and Intro Screen

In this white belt video we show you how to create the HTML canvas and add some basic styles to your canvas and page. We also showed you how to add an intro screen with some text. In this video we created 3 files which include index.html, style.css, game.js.

index.html

<!DOCTYPE html>
<html>
<head>
	<title>HTML5 Game</title>
	<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>

	<canvas id="game" width="640" height="360"></canvas>
	<script type="text/javascript" src="game.js"></script>

</body>
</html>

style.css

body{
	margin:0px;
	padding:0px;
	background:#222222;
}

#game{
	background:#ffffff;
	position:absolute;
	top:50%;
	left:50%;
	margin-left:-320px;
	margin-top:-180px;
}

game.js

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

context.font = "50px Impact";
context.fillStyle = "#0099CC";
context.textAlign = "center";
context.fillText("HTML5 Game", canvas.width/2, canvas.height/2);

context.font = "20px Arial";
context.fillText("Press Enter To Start", canvas.width/2, canvas.height/2 + 50);

Capturing Input & Game Loop

In this episode you will learn how to Add an Event Listener for keyboard input and we'll also show you how to create a game loop. Below is the code from the game.js file that we added in this video:

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

var gameStarted = false;

document.body.addEventListener("keydown", function(event){

	if(event.keyCode == 13 && !gameStarted){
		startGame();
	}

});

intro_screen();

function intro_screen(){
	context.font = "50px Impact";
	context.fillStyle = "#0099CC";
	context.textAlign = "center";
	context.fillText("HTML5 Game", canvas.width/2, canvas.height/2);

	context.font = "20px Arial";
	context.fillText("Press Enter To Start", canvas.width/2, canvas.height/2 + 50);
}

function startGame(){
	gameStarted = true;
	clearCanvas();

	setInterval(function(){
		clearCanvas();
		loop();
	}, 1000/30)
}

function loop(){
	console.log('game running');
}

function clearCanvas(){
	context.clearRect(0, 0, 640, 360);
}

Character Movement

In this video we'll show you how to create a player object and draw it to the screen and we'll also show you how to move the player around the screen. Below you will find the code that we added to create the character and move it around the canvas:

var canvas = document.getElementById('game');
var context = canvas.getContext('2d');
var gameStarted = false;
var keys = [];
var friction = 0.8;

var player = {
	x: 5,
	y: canvas.height - 20,
	width: 20,
	height: 20,
	speed: 5,
	velX: 0,
	velY: 0,
	color: "#ff0000",
	draw: function(){
		context.fillStyle = this.color;
		context.fillRect(this.x, this.y, this.width, this.height);
	}
}

document.body.addEventListener("keydown", function(event){

	if(event.keyCode == 13 && !gameStarted){
		startGame();
	}
	keys[event.keyCode] = true;

});

document.body.addEventListener("keyup", function(event){
	keys[event.keyCode] = false;
});

intro_screen();

function intro_screen(){
	context.font = "50px Impact";
	context.fillStyle = "#0099CC";
	context.textAlign = "center";
	context.fillText("HTML5 Game", canvas.width/2, canvas.height/2);

	context.font = "20px Arial";
	context.fillText("Press Enter To Start", canvas.width/2, canvas.height/2 + 50);
}

function startGame(){
	gameStarted = true;
	clearCanvas();

	setInterval(function(){
		clearCanvas();
		loop();
	}, 1000/30)
}

function loop(){

	player.draw();

	if(keys[39]){
		if(player.velX < player.speed){
			player.velX++;
		}
	}

	if(keys[37]){
		if(player.velX > -player.speed){
			player.velX--;
		}
	}

	player.x += player.velX;
	player.velX *= friction;

}

function clearCanvas(){
	context.clearRect(0, 0, 640, 360);
}

Character Jumping and Platforms

Let's add functionality to make our user jump. We'll also add the platforms for our game in this episode. Checkout the code below that we included in this episode:

var canvas = document.getElementById('game');
var context = canvas.getContext('2d');
var gameStarted = false;
var keys = [];
var friction = 0.8;
var gravity = 0.98;

var player = {
	x: 5,
	y: canvas.height - 20,
	width: 20,
	height: 20,
	speed: 5,
	velX: 0,
	velY: 0,
	color: "#ff0000",
	jumping: false,
	jumpStrength: 7,
	draw: function(){
		context.fillStyle = this.color;
		context.fillRect(this.x, this.y, this.width, this.height);
	}
}

var platforms = [];
var platform_width = 120;
var platform_height = 10;

platforms.push({
    x: canvas.width-170,
    y: 40,
    width: platform_width,
    height: platform_height,
});
platforms.push({
    x: canvas.width-170,
    y: canvas.height-50,
    width: platform_width,
    height: platform_height,
});
platforms.push({
    x: canvas.width-380,
    y: canvas.height-120,
    width: platform_width,
    height: platform_height,
});
platforms.push({
    x: canvas.width-380,
    y: canvas.height-240,
    width: platform_width,
    height: platform_height,
});

platforms.push({
    x: canvas.width-590,
    y: canvas.height-180,
    width: platform_width,
    height: platform_height,
});

document.body.addEventListener("keydown", function(event){

	if(event.keyCode == 13 && !gameStarted){
		startGame();
	}
	keys[event.keyCode] = true;

});

document.body.addEventListener("keyup", function(event){
	keys[event.keyCode] = false;
});

intro_screen();

function intro_screen(){
	context.font = "50px Impact";
	context.fillStyle = "#0099CC";
	context.textAlign = "center";
	context.fillText("HTML5 Game", canvas.width/2, canvas.height/2);

	context.font = "20px Arial";
	context.fillText("Press Enter To Start", canvas.width/2, canvas.height/2 + 50);
}

function startGame(){
	gameStarted = true;
	clearCanvas();

	setInterval(function(){
		clearCanvas();
		loop();
	}, 1000/30)
}

function draw_platforms(){
	context.fillStyle = "#333333";

	for(var i = 0; i < platforms.length; i++){
		context.fillRect(platforms[i].x, platforms[i].y, platforms[i].width, platforms[i].height);
	}
}

function loop(){

	draw_platforms();
	player.draw();

	if(keys[38] || keys[32]){
		if(!player.jumping){
			player.velY = -player.jumpStrength*2;
			player.jumping = true;
		}
	}

	if(keys[39]){
		if(player.velX < player.speed){
			player.velX++;
		}
	}

	if(keys[37]){
		if(player.velX > -player.speed){
			player.velX--;
		}
	}

	player.x += player.velX;
	player.y += player.velY;

	player.velX *= friction;
	player.velY += gravity;

	if(player.y >= canvas.height - player.height){
		player.y = canvas.height - player.height;
		player.jumping = false;
	}

}

function clearCanvas(){
	context.clearRect(0, 0, 640, 360);
}

Collision Detection

Collision Detection is when 2 objects are colliding with each other. When creating a platform game you will need to have collision detection in order for the character to jump on platforms. Checkout the code below that we created to perform collision detection in our game:

var canvas = document.getElementById('game');
var context = canvas.getContext('2d');
var gameStarted = false;
var keys = [];
var friction = 0.8;
var gravity = 0.98;

var player = {
	x: 5,
	y: canvas.height - 20,
	width: 20,
	height: 20,
	speed: 5,
	velX: 0,
	velY: 0,
	color: "#ff0000",
	jumping: false,
	grounded: false,
	jumpStrength: 7,
	draw: function(){
		context.fillStyle = this.color;
		context.fillRect(this.x, this.y, this.width, this.height);
	}
}

var platforms = [];
var platform_width = 120;
var platform_height = 10;

platforms.push({
    x: canvas.width-170,
    y: 40,
    width: platform_width,
    height: platform_height,
});
platforms.push({
    x: canvas.width-170,
    y: canvas.height-50,
    width: platform_width,
    height: platform_height,
});
platforms.push({
    x: canvas.width-380,
    y: canvas.height-120,
    width: platform_width,
    height: platform_height,
});
platforms.push({
    x: canvas.width-380,
    y: canvas.height-240,
    width: platform_width,
    height: platform_height,
});

platforms.push({
    x: canvas.width-590,
    y: canvas.height-180,
    width: platform_width,
    height: platform_height,
});

platforms.push({
	x: 0,
	y: canvas.height-5,
	width: canvas.width,
	height: platform_height
});

document.body.addEventListener("keydown", function(event){

	if(event.keyCode == 13 && !gameStarted){
		startGame();
	}
	keys[event.keyCode] = true;

});

document.body.addEventListener("keyup", function(event){
	keys[event.keyCode] = false;
});

intro_screen();

function intro_screen(){
	context.font = "50px Impact";
	context.fillStyle = "#0099CC";
	context.textAlign = "center";
	context.fillText("HTML5 Game", canvas.width/2, canvas.height/2);

	context.font = "20px Arial";
	context.fillText("Press Enter To Start", canvas.width/2, canvas.height/2 + 50);
}

function startGame(){
	gameStarted = true;
	clearCanvas();

	setInterval(function(){
		clearCanvas();
		loop();
	}, 1000/30)
}

function draw_platforms(){
	context.fillStyle = "#333333";

	for(var i = 0; i < platforms.length; i++){
		context.fillRect(platforms[i].x, platforms[i].y, platforms[i].width, platforms[i].height);
	}
}

function loop(){

	draw_platforms();
	player.draw();

	if(keys[38] || keys[32]){
		if(!player.jumping){
			player.velY = -player.jumpStrength*2;
			player.jumping = true;
		}
	}

	if(keys[39]){
		if(player.velX < player.speed){
			player.velX++;
		}
	}

	if(keys[37]){
		if(player.velX > -player.speed){
			player.velX--;
		}
	}

	player.x += player.velX;
	player.y += player.velY;

	player.velX *= friction;
	player.velY += gravity;

	player.grounded = false;
	for(var i = 0; i < platforms.length; i++){
		var direction = collisionCheck(player, platforms[i]);

		if(direction == "left" || direction == "right"){
			player.velX = 0;
		} else if(direction == "bottom"){
			player.jumping = false;
			player.grounded = true;
		} else if(direction == "top"){
			player.velY *= -1;
		}

	}

	if(player.grounded){
		player.velY = 0;
	}

}

function collisionCheck(character, platform){

	var vectorX = (character.x + (character.width/2)) - (platform.x + (platform.width/2));
	var vectorY = (character.y + (character.height/2)) - (platform.y + (platform.height/2));

	var halfWidths = (character.width/2) + (platform.width/2);
	var halfHeights = (character.height/2) + (platform.height/2);

	var collisionDirection = null;

	if(Math.abs(vectorX) < halfWidths && Math.abs(vectorY) < halfHeights){

		var offsetX = halfWidths - Math.abs(vectorX);
		var offsetY = halfHeights - Math.abs(vectorY);
		if(offsetX < offsetY){

			if (vectorX > 0){
				collisionDirection = "left";
				character.x += offsetX;
			} else {
				collisionDirection = "right";
				character.x -= offsetX;
			}

		} else {

			if (vectorY > 0){
				collisionDirection = "top";
				character.y += offsetY;
			} else {
				collisionDirection = "bottom";
				character.y -= offsetY;
			}

		}

	}

	return collisionDirection;

}

function clearCanvas(){
	context.clearRect(0, 0, 640, 360);
}

Animation Loop, Walls, and Ceiling

Instead of using the setInterval function for our game loop, there is a better function we can use. We'll also be adding walls and a ceiling platform in this video. Check out the code we used below:

var canvas = document.getElementById('game');
var context = canvas.getContext('2d');
var gameStarted = false;
var keys = [];
var friction = 0.8;
var gravity = 0.98;

var player = {
	x: 5,
	y: canvas.height - 20,
	width: 20,
	height: 20,
	speed: 5,
	velX: 0,
	velY: 0,
	color: "#ff0000",
	jumping: false,
	grounded: false,
	jumpStrength: 7,
	draw: function(){
		context.fillStyle = this.color;
		context.fillRect(this.x, this.y, this.width, this.height);
	}
}

var platforms = [];
var platform_width = 120;
var platform_height = 10;

platforms.push({
    x: canvas.width-170,
    y: 40,
    width: platform_width,
    height: platform_height,
});
platforms.push({
    x: canvas.width-170,
    y: canvas.height-50,
    width: platform_width,
    height: platform_height,
});
platforms.push({
    x: canvas.width-380,
    y: canvas.height-120,
    width: platform_width,
    height: platform_height,
});
platforms.push({
    x: canvas.width-380,
    y: canvas.height-240,
    width: platform_width,
    height: platform_height,
});

platforms.push({
    x: canvas.width-590,
    y: canvas.height-180,
    width: platform_width,
    height: platform_height,
});

// Floor
platforms.push({
	x: 0,
	y: canvas.height-5,
	width: canvas.width,
	height: platform_height
});

// Left Wall
platforms.push({
	x: -10,
	y: 0,
	width: 10,
	height: canvas.height
});

// Left Wall
platforms.push({
	x: canvas.width,
	y: 0,
	width: 10,
	height: canvas.height
});

// Floor
platforms.push({
	x: 0,
	y: -10,
	width: canvas.width,
	height: platform_height
});

document.body.addEventListener("keydown", function(event){

	if(event.keyCode == 13 && !gameStarted){
		startGame();
	}
	keys[event.keyCode] = true;

});

document.body.addEventListener("keyup", function(event){
	keys[event.keyCode] = false;
});

intro_screen();

function intro_screen(){
	context.font = "50px Impact";
	context.fillStyle = "#0099CC";
	context.textAlign = "center";
	context.fillText("HTML5 Game", canvas.width/2, canvas.height/2);

	context.font = "20px Arial";
	context.fillText("Press Enter To Start", canvas.width/2, canvas.height/2 + 50);
}

function startGame(){
	gameStarted = true;
	clearCanvas();

	requestAnimationFrame(loop);

}

function draw_platforms(){
	context.fillStyle = "#333333";

	for(var i = 0; i < platforms.length; i++){
		context.fillRect(platforms[i].x, platforms[i].y, platforms[i].width, platforms[i].height);
	}
}

function loop(){

	clearCanvas();
	draw_platforms();
	player.draw();

	if(keys[38] || keys[32]){
		if(!player.jumping){
			player.velY = -player.jumpStrength*2;
			player.jumping = true;
		}
	}

	if(keys[39]){
		if(player.velX < player.speed){
			player.velX++;
		}
	}

	if(keys[37]){
		if(player.velX > -player.speed){
			player.velX--;
		}
	}

	player.x += player.velX;
	player.y += player.velY;

	player.velX *= friction;
	player.velY += gravity;

	player.grounded = false;
	for(var i = 0; i < platforms.length; i++){
		var direction = collisionCheck(player, platforms[i]);

		if(direction == "left" || direction == "right"){
			player.velX = 0;
		} else if(direction == "bottom"){
			player.jumping = false;
			player.grounded = true;
		} else if(direction == "top"){
			player.velY *= -1;
		}

	}

	if(player.grounded){
		player.velY = 0;
	}

	requestAnimationFrame(loop);

}

function collisionCheck(character, platform){

	var vectorX = (character.x + (character.width/2)) - (platform.x + (platform.width/2));
	var vectorY = (character.y + (character.height/2)) - (platform.y + (platform.height/2));

	var halfWidths = (character.width/2) + (platform.width/2);
	var halfHeights = (character.height/2) + (platform.height/2);

	var collisionDirection = null;

	if(Math.abs(vectorX) < halfWidths && Math.abs(vectorY) < halfHeights){

		var offsetX = halfWidths - Math.abs(vectorX);
		var offsetY = halfHeights - Math.abs(vectorY);
		if(offsetX < offsetY){

			if (vectorX > 0){
				collisionDirection = "left";
				character.x += offsetX;
			} else {
				collisionDirection = "right";
				character.x -= offsetX;
			}

		} else {

			if (vectorY > 0){
				collisionDirection = "top";
				character.y += offsetY;
			} else {
				collisionDirection = "bottom";
				character.y -= offsetY;
			}

		}

	}

	return collisionDirection;

}

function clearCanvas(){
	context.clearRect(0, 0, 640, 360);
}

Adding a Goal & Resetting the Game

In this video we'll show you how to add a goal that the user can try and collide with in order to complete the level. We'll also create a new function that will reset the game. Below is the code that we used in this video:

var canvas = document.getElementById('game');
var context = canvas.getContext('2d');
var gameStarted = false;
var keys = [];
var friction = 0.8;
var gravity = 0.98;
var completed = false;

var player = {
	x: 5,
	y: canvas.height - 25,
	width: 20,
	height: 20,
	speed: 5,
	velX: 0,
	velY: 0,
	color: "#ff0000",
	jumping: false,
	grounded: false,
	jumpStrength: 7,
	draw: function(){
		context.fillStyle = this.color;
		context.fillRect(this.x, this.y, this.width, this.height);
	}
}

var goal = {
	x: canvas.width-80,
	y: 5,
	width:30,
	height:35,
	color: "#0098cb",
	draw: function(){
		context.fillStyle = this.color;
		context.fillRect(this.x, this.y, this.width, this.height);
	}
}

var platforms = [];
var platform_width = 120;
var platform_height = 10;

platforms.push({
    x: canvas.width-170,
    y: 40,
    width: platform_width,
    height: platform_height,
});
platforms.push({
    x: canvas.width-170,
    y: canvas.height-50,
    width: platform_width,
    height: platform_height,
});
platforms.push({
    x: canvas.width-380,
    y: canvas.height-120,
    width: platform_width,
    height: platform_height,
});
platforms.push({
    x: canvas.width-380,
    y: canvas.height-240,
    width: platform_width,
    height: platform_height,
});

platforms.push({
    x: canvas.width-590,
    y: canvas.height-180,
    width: platform_width,
    height: platform_height,
});

// Floor
platforms.push({
	x: 0,
	y: canvas.height-5,
	width: canvas.width,
	height: platform_height
});

// Left Wall
platforms.push({
	x: -10,
	y: 0,
	width: 10,
	height: canvas.height
});

// Left Wall
platforms.push({
	x: canvas.width,
	y: 0,
	width: 10,
	height: canvas.height
});

// Floor
platforms.push({
	x: 0,
	y: -10,
	width: canvas.width,
	height: platform_height
});

document.body.addEventListener("keydown", function(event){

	if(event.keyCode == 13 && !gameStarted){
		startGame();
	}
	if(event.keyCode == 13 && completed){
		reset();
	}
	keys[event.keyCode] = true;

});

document.body.addEventListener("keyup", function(event){
	keys[event.keyCode] = false;
});

intro_screen();

function intro_screen(){
	context.font = "50px Impact";
	context.fillStyle = "#0099CC";
	context.textAlign = "center";
	context.fillText("HTML5 Game", canvas.width/2, canvas.height/2);

	context.font = "20px Arial";
	context.fillText("Press Enter To Start", canvas.width/2, canvas.height/2 + 50);
}

function startGame(){
	gameStarted = true;
	clearCanvas();

	requestAnimationFrame(loop);

}

function complete(){
	clearCanvas();
	completed = true;

	context.font = "50px Impact";
	context.fillStyle = "#0099CC";
	context.textAlign = "center";
	context.fillText("Congrats! You've Won!", canvas.width/2, canvas.height/2);

	context.font = "20px Arial";
	context.fillText("Press Enter to Play Again", canvas.width/2, canvas.height/2 + 50);
}

function reset(){
	player.x = 5;
	player.y = canvas.height-25;
	player.grounded = true;
	player.velY = 0;
	player.velX = 0;
	completed = false;

	requestAnimationFrame(loop);
}

function draw_platforms(){
	context.fillStyle = "#333333";

	for(var i = 0; i < platforms.length; i++){
		context.fillRect(platforms[i].x, platforms[i].y, platforms[i].width, platforms[i].height);
	}
}

function loop(){

	clearCanvas();
	draw_platforms();
	player.draw();
	goal.draw();

	if(keys[38] || keys[32]){
		if(!player.jumping){
			player.velY = -player.jumpStrength*2;
			player.jumping = true;
		}
	}

	if(keys[39]){
		if(player.velX < player.speed){
			player.velX++;
		}
	}

	if(keys[37]){
		if(player.velX > -player.speed){
			player.velX--;
		}
	}

	player.x += player.velX;
	player.y += player.velY;

	player.velX *= friction;
	player.velY += gravity;

	player.grounded = false;
	for(var i = 0; i < platforms.length; i++){
		var direction = collisionCheck(player, platforms[i]);

		if(direction == "left" || direction == "right"){
			player.velX = 0;
		} else if(direction == "bottom"){
			player.jumping = false;
			player.grounded = true;
		} else if(direction == "top"){
			player.velY *= -1;
		}

	}

	if(player.grounded){
		player.velY = 0;
	}

	if(collisionCheck(player, goal)){
		complete();
	}

	if(!completed){
		requestAnimationFrame(loop);
	}

}

function collisionCheck(character, platform){

	var vectorX = (character.x + (character.width/2)) - (platform.x + (platform.width/2));
	var vectorY = (character.y + (character.height/2)) - (platform.y + (platform.height/2));

	var halfWidths = (character.width/2) + (platform.width/2);
	var halfHeights = (character.height/2) + (platform.height/2);

	var collisionDirection = null;

	if(Math.abs(vectorX) < halfWidths && Math.abs(vectorY) < halfHeights){

		var offsetX = halfWidths - Math.abs(vectorX);
		var offsetY = halfHeights - Math.abs(vectorY);
		if(offsetX < offsetY){

			if (vectorX > 0){
				collisionDirection = "left";
				character.x += offsetX;
			} else {
				collisionDirection = "right";
				character.x -= offsetX;
			}

		} else {

			if (vectorY > 0){
				collisionDirection = "top";
				character.y += offsetY;
			} else {
				collisionDirection = "bottom";
				character.y -= offsetY;
			}

		}

	}

	return collisionDirection;

}

function clearCanvas(){
	context.clearRect(0, 0, 640, 360);
}

Images and Platform Styles

In this video we'll be adding images and adding more styles to the platform in our game. Checkout the code below that we have added to the game throughout this video:

var canvas = document.getElementById('game');
var context = canvas.getContext('2d');
var gameStarted = false;
var keys = [];
var friction = 0.8;
var gravity = 0.98;
var completed = false;

var door_image = new Image();
door_image.src = "door.png";

var image = new Image();
image.src = "character.png";

var player = {
	x: 5,
	y: canvas.height - 45,
	width: 40,
	height: 40,
	speed: 5,
	velX: 0,
	velY: 0,
	color: "#ff0000",
	jumping: false,
	grounded: false,
	jumpStrength: 7,
	position: "idle",
	draw: function(){	
		startX = 40;
		if(this.position == "left"){
			startX = 0;
		} else if(this.position == "right"){
			startX = 80;
		}
		context.drawImage(image, startX, 0, 40, 40, this.x, this.y, 40, 40);
	}
}

var goal = {
	x: canvas.width-90,
	y: 0,
	width:40,
	height:45,
	color: "#0098cb",
	draw: function(){
		context.drawImage(door_image, this.x, this.y);
	}
}

var platforms = [];
var platform_width = 120;
var platform_height = 10;

platforms.push({
    x: canvas.width-170,
    y: 50,
    width: platform_width,
    height: platform_height,
});
platforms.push({
    x: canvas.width-170,
    y: canvas.height-50,
    width: platform_width,
    height: platform_height,
});
platforms.push({
    x: canvas.width-380,
    y: canvas.height-120,
    width: platform_width,
    height: platform_height,
});
platforms.push({
    x: canvas.width-380,
    y: canvas.height-240,
    width: platform_width,
    height: platform_height,
});

platforms.push({
    x: canvas.width-590,
    y: canvas.height-180,
    width: platform_width,
    height: platform_height,
});

// Floor
platforms.push({
	x: 0,
	y: canvas.height-5,
	width: canvas.width,
	height: platform_height
});

// Left Wall
platforms.push({
	x: -10,
	y: 0,
	width: 10,
	height: canvas.height
});

// Left Wall
platforms.push({
	x: canvas.width,
	y: 0,
	width: 10,
	height: canvas.height
});

// Floor
platforms.push({
	x: 0,
	y: -10,
	width: canvas.width,
	height: platform_height
});

document.body.addEventListener("keydown", function(event){

	if(event.keyCode == 13 && !gameStarted){
		startGame();
	}
	if(event.keyCode == 13 && completed){
		reset();
	}
	keys[event.keyCode] = true;

});

document.body.addEventListener("keyup", function(event){
	keys[event.keyCode] = false;
});

intro_screen();

function intro_screen(){
	context.font = "50px Impact";
	context.fillStyle = "#0099CC";
	context.textAlign = "center";
	context.fillText("HTML5 Game", canvas.width/2, canvas.height/2);

	context.font = "20px Arial";
	context.fillText("Press Enter To Start", canvas.width/2, canvas.height/2 + 50);
}

function startGame(){
	gameStarted = true;
	clearCanvas();

	requestAnimationFrame(loop);

}

function complete(){
	clearCanvas();
	completed = true;

	context.font = "50px Impact";
	context.fillStyle = "#0099CC";
	context.textAlign = "center";
	context.fillText("Congrats! You've Won!", canvas.width/2, canvas.height/2);

	context.font = "20px Arial";
	context.fillText("Press Enter to Play Again", canvas.width/2, canvas.height/2 + 50);
}

function reset(){
	player.x = 5;
	player.y = canvas.height-25;
	player.grounded = true;
	player.velY = 0;
	player.velX = 0;
	completed = false;

	requestAnimationFrame(loop);
}

function draw_platforms(){
	context.fillStyle = "#907020";

	for(var i = 0; i < platforms.length; i++){
		context.fillRect(platforms[i].x, platforms[i].y, platforms[i].width, platforms[i].height);
		context.lineWidth = 5;
		context.strokeStyle = "#90D030";
		context.strokeRect(platforms[i].x, platforms[i].y-2, platforms[i].width, 5);
	}
}

function loop(){

	clearCanvas();
	draw_platforms();
	player.draw();
	goal.draw();

	player.position = "idle";

	if(keys[38] || keys[32]){
		if(!player.jumping){
			player.velY = -player.jumpStrength*2;
			player.jumping = true;
		}
	}

	if(keys[39]){
		player.position = "right";
		if(player.velX < player.speed){
			player.velX+=2;
		}
	}

	if(keys[37]){
		player.position = "left";
		if(player.velX > -player.speed){
			player.velX-=2;
		}
	}

	player.x += player.velX;
	player.y += player.velY;

	player.velX *= friction;
	player.velY += gravity;

	player.grounded = false;
	for(var i = 0; i < platforms.length; i++){
		var direction = collisionCheck(player, platforms[i]);

		if(direction == "left" || direction == "right"){
			player.velX = 0;
		} else if(direction == "bottom"){
			player.jumping = false;
			player.grounded = true;
		} else if(direction == "top"){
			player.velY *= -1;
		}

	}

	if(player.grounded){
		player.velY = 0;
	}

	if(collisionCheck(player, goal)){
		complete();
	}

	if(!completed){
		requestAnimationFrame(loop);
	}

}

function collisionCheck(character, platform){

	var vectorX = (character.x + (character.width/2)) - (platform.x + (platform.width/2));
	var vectorY = (character.y + (character.height/2)) - (platform.y + (platform.height/2));

	var halfWidths = (character.width/2) + (platform.width/2);
	var halfHeights = (character.height/2) + (platform.height/2);

	var collisionDirection = null;

	if(Math.abs(vectorX) < halfWidths && Math.abs(vectorY) < halfHeights){

		var offsetX = halfWidths - Math.abs(vectorX);
		var offsetY = halfHeights - Math.abs(vectorY);
		if(offsetX < offsetY){

			if (vectorX > 0){
				collisionDirection = "left";
				character.x += offsetX;
			} else {
				collisionDirection = "right";
				character.x -= offsetX;
			}

		} else {

			if (vectorY > 0){
				collisionDirection = "top";
				character.y += offsetY;
			} else {
				collisionDirection = "bottom";
				character.y -= offsetY;
			}

		}

	}

	return collisionDirection;

}

function clearCanvas(){
	context.clearRect(0, 0, 640, 360);
}

Adding Backgrounds and Wrapping Up

In this final video we'll be adding the background images for our site and wrapping up the game. I really hope you enjoyed this course and I hope that you have learned a lot about html 5 game development. Below is the final code for the HTML, CSS, and the Javascript file:

index.html

<!DOCTYPE html>
<html>
<head>
	<title>HTML5 Game</title>
	<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>

	<div id="background"></div>
	<canvas id="game" width="640" height="360"></canvas>
	<script type="text/javascript" src="game.js"></script>

</body>
</html>

style.css

html, body{
	width:100%;
	height:100%;
}

body{
	margin:0px;
	padding:0px;
	background:#222222;
	background-image:url('bg.png');
	background-size:cover;
	background-position: center center;
	background-repeat: no-repeat;
}

#background{
	width:800px;
	height:600px;
	position:absolute;
	top:50%;
	left:50%;
	margin-left:-400px;
	margin-top:-300px;
	background:url('background.png');
	background-repeat: no-repeat;
	z-index:9;
}

#game{
	background:url('gamebg.jpg');
	position:absolute;
	top:50%;
	left:50%;
	margin-left:-320px;
	margin-top:-180px;
}

game.js

var canvas = document.getElementById('game');
var context = canvas.getContext('2d');
var gameStarted = false;
var keys = [];
var friction = 0.8;
var gravity = 0.98;
var completed = false;

var door_image = new Image();
door_image.src = "door.png";

var image = new Image();
image.src = "character.png";

var player = {
	x: 5,
	y: canvas.height - 45,
	width: 40,
	height: 40,
	speed: 5,
	velX: 0,
	velY: 0,
	color: "#ff0000",
	jumping: false,
	grounded: false,
	jumpStrength: 7,
	position: "idle",
	draw: function(){	
		startX = 40;
		if(this.position == "left"){
			startX = 0;
		} else if(this.position == "right"){
			startX = 80;
		}
		context.drawImage(image, startX, 0, 40, 40, this.x, this.y, 40, 40);
	}
}

var goal = {
	x: canvas.width-90,
	y: 0,
	width:40,
	height:45,
	color: "#0098cb",
	draw: function(){
		context.drawImage(door_image, this.x, this.y);
	}
}

var platforms = [];
var platform_width = 120;
var platform_height = 10;

platforms.push({
    x: canvas.width-170,
    y: 50,
    width: platform_width,
    height: platform_height,
});
platforms.push({
    x: canvas.width-170,
    y: canvas.height-50,
    width: platform_width,
    height: platform_height,
});
platforms.push({
    x: canvas.width-380,
    y: canvas.height-120,
    width: platform_width,
    height: platform_height,
});
platforms.push({
    x: canvas.width-380,
    y: canvas.height-240,
    width: platform_width,
    height: platform_height,
});

platforms.push({
    x: canvas.width-590,
    y: canvas.height-180,
    width: platform_width,
    height: platform_height,
});

// Floor
platforms.push({
	x: 0,
	y: canvas.height-5,
	width: canvas.width,
	height: platform_height
});

// Left Wall
platforms.push({
	x: -10,
	y: 0,
	width: 10,
	height: canvas.height
});

// Left Wall
platforms.push({
	x: canvas.width,
	y: 0,
	width: 10,
	height: canvas.height
});

// Floor
platforms.push({
	x: 0,
	y: -10,
	width: canvas.width,
	height: platform_height
});

document.body.addEventListener("keydown", function(event){

	if(event.keyCode == 13 && !gameStarted){
		startGame();
	}
	if(event.keyCode == 13 && completed){
		reset();
	}
	keys[event.keyCode] = true;

});

document.body.addEventListener("keyup", function(event){
	keys[event.keyCode] = false;
});

intro_screen();

function intro_screen(){
	context.font = "50px Impact";
	context.fillStyle = "#FFFFFF";
	context.textAlign = "center";
	context.fillText("HTML5 Game", canvas.width/2, canvas.height/2);

	context.font = "20px Arial";
	context.fillText("Press Enter To Start", canvas.width/2, canvas.height/2 + 50);
}

function startGame(){
	gameStarted = true;
	clearCanvas();

	requestAnimationFrame(loop);

}

function complete(){
	clearCanvas();
	completed = true;

	context.font = "50px Impact";
	context.fillStyle = "#FFFFFF";
	context.textAlign = "center";
	context.fillText("Congrats! You've Won!", canvas.width/2, canvas.height/2);

	context.font = "20px Arial";
	context.fillText("Press Enter to Play Again", canvas.width/2, canvas.height/2 + 50);
}

function reset(){
	player.x = 5;
	player.y = canvas.height-25;
	player.grounded = true;
	player.velY = 0;
	player.velX = 0;
	completed = false;

	requestAnimationFrame(loop);
}

function draw_platforms(){
	context.fillStyle = "#907020";

	for(var i = 0; i < platforms.length; i++){
		context.fillRect(platforms[i].x, platforms[i].y, platforms[i].width, platforms[i].height);
		context.lineWidth = 5;
		context.strokeStyle = "#90D030";
		context.strokeRect(platforms[i].x, platforms[i].y-2, platforms[i].width, 5);
	}
}

function loop(){

	clearCanvas();
	draw_platforms();
	player.draw();
	goal.draw();

	player.position = "idle";

	if(keys[38] || keys[32]){
		if(!player.jumping){
			player.velY = -player.jumpStrength*2;
			player.jumping = true;
		}
	}

	if(keys[39]){
		player.position = "right";
		if(player.velX < player.speed){
			player.velX+=2;
		}
	}

	if(keys[37]){
		player.position = "left";
		if(player.velX > -player.speed){
			player.velX-=2;
		}
	}

	player.x += player.velX;
	player.y += player.velY;

	player.velX *= friction;
	player.velY += gravity;

	player.grounded = false;
	for(var i = 0; i < platforms.length; i++){
		var direction = collisionCheck(player, platforms[i]);

		if(direction == "left" || direction == "right"){
			player.velX = 0;
		} else if(direction == "bottom"){
			player.jumping = false;
			player.grounded = true;
		} else if(direction == "top"){
			player.velY *= -1;
		}

	}

	if(player.grounded){
		player.velY = 0;
	}

	if(collisionCheck(player, goal)){
		complete();
	}

	if(!completed){
		requestAnimationFrame(loop);
	}

}

function collisionCheck(character, platform){

	var vectorX = (character.x + (character.width/2)) - (platform.x + (platform.width/2));
	var vectorY = (character.y + (character.height/2)) - (platform.y + (platform.height/2));

	var halfWidths = (character.width/2) + (platform.width/2);
	var halfHeights = (character.height/2) + (platform.height/2);

	var collisionDirection = null;

	if(Math.abs(vectorX) < halfWidths && Math.abs(vectorY) < halfHeights){

		var offsetX = halfWidths - Math.abs(vectorX);
		var offsetY = halfHeights - Math.abs(vectorY);
		if(offsetX < offsetY){

			if (vectorX > 0){
				collisionDirection = "left";
				character.x += offsetX;
			} else {
				collisionDirection = "right";
				character.x -= offsetX;
			}

		} else {

			if (vectorY > 0){
				collisionDirection = "top";
				character.y += offsetY;
			} else {
				collisionDirection = "bottom";
				character.y -= offsetY;
			}

		}

	}

	return collisionDirection;

}

function clearCanvas(){
	context.clearRect(0, 0, 640, 360);
}

Hope you enjoyed this course. Happy Game Coding :)

Introduction

10 videos (1 hour and 1 minute)

Autoplay?

0% completed
Now Playing 1. Introduction
2. Drawing the Canvas and Intro Screen
3. Capturing Input & Game Loop
4. Character Movement
5. Character Jumping and Platforms
6. Collision Detection
7. Animation Loop, Walls, and Ceiling
8. Adding a Goal & Resetting the Game
9. Images and Platform Styles
10. Adding Backgrounds and Wrapping Up
Back to DevDojo