HTML 5 Game Development Part 1

What I learned while preparing my presentation for the August MTS

Sacha Morgese
henngeblog
11 min readOct 22, 2018

--

About this article

I think every gamer has thought at least once in his/her life “I want to make my own game!”, and I am no different. As a matter of fact, I would spend countless hours in junior high creating adventure games on paper to play with my best friend during school, and it was a lot of fun. It was fun coming up with ridiculous characters and absurd weapons and it was fun to have my friend fall into my traps and struggle to solve my puzzles (don’t feel bad for him, he would do the exact same thing the next day). It was one of the reasons why I decided to study some programming in high school. However, in the early 2000s, the internet was a different place than today and I lacked both the means and the initiative to start and learn some game programming on my own.

A few months ago I ended up receiving (legally) a pdf copy of a book called HTML5 Games: Novice to Ninja, put it in my Kindle Fire and kinda forgot about it until I was asked to make a presentation for our Monthly Technical Session ad HDE. Being one of the few front-end developers at the company I was thinking of talking about something that would be entertaining for everyone, not only to people with knowledge of JavaScript. After considering all the options I decided to make a presentation about Game Development in HTML5, thinking that my knowledge of JavaScript and front-end, in general, would allow me to create a working demo in just a few hours of work.

I was wrong. Of course, I was wrong. Game development is hard.
The few hours I thought I needed became a couple week full of reading, learning and wanting to bang my head on the wall and even though I had great ideas for the presentation, in the end, I could only show a working demo taken from the book. A little disappointing, yes, but only because I underestimated the time required to grasp the basics. On top of that, I am the kind of developer who doesn’t like to learn something new focusing only on the parts necessary to complete the task. I really like to understand as deeply as I can the tools that I am using and everything around them. It might sound like a waste of time to many, but I prefer to spend a little more time preparing for the trip instead of having to stop several times to look at the map.

It was a worthwhile journey, although just a prelude to something much, much bigger, and I had quite a few “EUREKA” moments that I like to think improved my skills as a coder.

Fundamentals concepts

Game development is hard, but the basics concepts that all games have in common are not hard to understand. Creating a videogame is pretty much like creating an animation on paper. Draw a lot of frames one after another and the human eye will do the magic and give the impression of motion. As simple as that. Of course, there’s a huge difference between an anime, where the outcome is always the same, and a game, where the user input dictates what the next frame will be, but the concept is the same.

In game development we don’t draw each individual frame, we tell the computer what to do and it draws for us, taking into consideration user input and collisions/changes. And this happens constantly, in a loop that fetches user input, moves everything a little, calculates collisions/changes and then draws the scene, usually 60 times per second. This concept is as true for old indie ASCII games as it is for AAA productions on modern platforms and everything in between.

A lot of modern tools for game development (Unity is probably the most popular out there) allow the user to focus on creating content offloading some cumbersome tasks to the engine, but what happens when you look under the hood is what I described in the previous paragraph. That means that mastering these concepts is the only way to be able to change each individual part of your product.

What said so far is generic and true for all kind of games and platforms, what about HTML 5 Game Development then?

HTML 5 Game Development

To put it simple, HTML 5 Game Development is what we call game development that runs in a browser, that uses the exact same languages and tools of front-end development. By knowing HTML, CSS and JavaScript it is already possible to create simple games able to run on your every platform equipped with a browser. But that has been possible for a long time and, although some pretty addictive games can be created using that technology, to talk about HTML 5 game development is to talk about the canvas API.

Created by Apple as an alternative to Flash, canvas is a simple yet powerful api that allows to draw graphics via scripting, having control on every single individual pixel. It can be used for both 2D graphics and 3D graphics (through webgl), but in this series of articles I will focus on 2D since it is the only context I have experience with and doesn’t require use to learn to use a completely different language.

Okay, great but… why HTML 5 then? What are the advantages?

JavaScript is one of the most popular programming languages in the world (first on GitHub) and that means the community and the support you can receive is unparalleled.
Making a game that runs in a browser means that the user doesn’t have to update it, since every time they run it they are automatically using the latest version.
And since browser nowadays get updated automatically, that means you can use everything your target browsers support without having to worry about leaving some users behind, since it simply what happen.
Also, since it runs in a browser, the users don’t need to install any extra library or tool. Isn’t it great?

Let’s get to it!

Let’s see how Canvas works with a couple of simple examples, moving our first steps in game development.
Canvas is nothing more but a simple way to draw things, but as I said before, animating means to draw one frame after another to give that impression of movement.

Let’s create a simple square. We’ll start by adding an html file. As you can see it doesn’t contain anything but a canvas nested in a div.

---------------------------- index.html ----------------------------<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Game</title>
<style>
body {
margin: 30px auto;
text-align: center;
color: #999;
}

#board canvas {
border: 1px solid #333;
background-color: #000;
-webkit-box-shadow: 0px 0px 24px 0px rgba(0,0,0,1);
-moz-box-shadow: 0px 0px 24px 0px rgba(0,0,0,1);
box-shadow: 0px 0px 24px 0px rgba(0,0,0,1);
border-radius: 10px;
}
</style>
</head>
<body>
<div id="board">
<canvas width="640" height="480"></canvas>
</div>
<script src="script.js"></script>
</body>
</html>

We are going to create the script file next. The first lines of our script.js are the following.

----------------------------- script.js ----------------------------const canvas = document.querySelector('#board canvas');
const ctx = canvas.getContext('2d');
console.log(ctx)

Let’s open our html file in a browser and you can admire your softly styled canvas. Ok, nothing special so far, the fun part starts now. Let’s draw a square!

----------------------------- script.js ----------------------------[...]const { width: w, height: h } = canvas;let x = w / 2;
let y = h / 2;
// Set the color
ctx.fillStyle = 'yellow'
// Create the square
ctx.fillRect(x, y, 50, 50)

And magic! A yellow square appeared. But how?
Well, we simply told our canvas to set the color (we can use CSS properties such as rgb and hsl there instead of a simple yellow) and then to fill a rectangle.
The numbers we passed as parameters are x and y coordinates (with 0, 0 being the top-left corner), width and height.
Want to move the square around? Try to play with the first two numbers. Want to make it bigger or make it a rectangle? Play with the last two.

Let’s center it now.

----------------------------- script.js ----------------------------[...]const { width: w, height: h } = canvas;

let rectW = 50;
let rectH = 50;
let x = w / 2 - rectW / 2;
let y = h / 2 - rectH / 2;
// Set the color
ctx.fillStyle = 'yellow'
// Create the square
ctx.fillRect(x, y, rectW, rectH)

In the first line (after getting the context) we are getting the width and height of the current canvas. We are then declaring two variables for the rectangle width and height and two for the coordinates. Our yellow rectangle is now centered. Great job!

Rectangles aren’t the only shapes we can create using canvas but are the only shapes with a dedicated command. Everything else is drawn using a “path”, but we won’t talk about that in this article for a couple of reasons. First, it is way more complicated than drawing rectangles and this article doesn’t need to be any longer. Second, you can import images and SVGs made using different tools. To learn more check the Canvas API page on MDN (or become a pro following the tutorial).

I loop, therefore I am

As I said before, an animation is nothing more than a series of images drawn one after another. We could draw each single frame one at the time and that would work but would be kinda pointless since we are trying to make games here. What we will do, instead, is creating a function that runs once per frame (60 times per second) and will draw each time the same rectangle but in a slightly different place.

How do we create a loop though? Using something like a while would lock the entire browser right away. SetTimeout and SetInterval work, but are a little too inconsistent to guarantee a frame each 16.7 seconds (more about those issues here) and consistency is crucial when it comes to games. Luckily, JavaScript helps us achieve our goal by using a function called requestAnimationFrame. It takes a function as a callback and executes it on the next frame. To make it work as a loop we need to call it in our main function to make it sure it’s executed on the next frame as well.

----------------------------- script.js ----------------------------function loop() {
// We need to call requestAnimationFrame again to tell it to run on the next refresh
requestAnimationFrame
(loop)
// A simple check to make the square reappears once out of the screen
if(x >= w + rectW) {
x = 0 - rectW
}
// Each frame adds 1 to the x coordinate, moving right 1 pixel
else {
x += 1
}
// Set the color
ctx.fillStyle = 'yellow'
// Create the square
ctx.fillRect(x, y, rectW, rectH)
}
// On the next frame, run our loop function
requestAnimationFrame(loop)

The square is moving! You just created a basic animation, isn’t it great?
But wait, it’s not just moving, it looks like it’s leaving a trail. Of course it is! We are leaving what we drew on our previous frame on the screen. Let’s get rid of that by deleting everything on screen.

----------------------------- script.js ----------------------------[...]// Set the color to black to 'clean' the screen
ctx.fillStyle = 'black'
// Paint it black!
ctx.fillRect(0, 0, w, h)
// Set the color
ctx.fillStyle = 'yellow'

Oh, now we’re talking! You can make it go faster by increasing the amount of pixels to add every frame.

Well, it took us a while but we’re finally able to se something move. It is still far from being interactive. Let’s create some keyboard controls to move our square.

Since we are working with a single JS file (to make things simple for this post), we will write this on top of everything we wrote before.

----------------------------- script.js ----------------------------class KeyControls {
constructor() {
// Keys will store the keys we are currently pressing
this.keys = {};
// Bind event handlers
document.addEventListener(
'keydown',
e => {
if ([37, 38, 39, 40].indexOf(e.which) >= 0) {
// To avoid scrolling the page with arrows
e.preventDefault();
}
// Set the pressed keys to true
this.keys[e.which] = true;
},
false,
);

document.addEventListener(
'keyup',
e => {
// set the released key to false
this.keys[e.which] = false;
},
false,
);
}

// Return true if the action button (space) is pressed
get action() {
return this.keys[32];
}

get x() {
// Return -1 if left arrow or A key are pressed
if (this.keys[37] || this.keys[65]) return -1;
// Return 1 if right arrow or D key are pressed
if (this.keys[39] || this.keys[68]) return 1;
return 0;
}

get y() {
// Return -1 if up arrow or W key are pressed
if (this.keys[38] || this.keys[87]) return -1;
// Return 1 if down arrow or S key are pressed
if (this.keys[40] || this.keys[83]) return 1;
return 0;
}
}

It might look complicated at first, but by checking the code you can see it doesn’t do anything but taking every key we press and setting it to true inside the keys object and setting it to false the moment we release it.

In addition, it returns +1 or -1 for the x and y getters, depending on the button pressed.

Let’s see it in action.

----------------------------- script.js ----------------------------class KeyControls {
[...]
}
const controls = new KeyControls

const canvas = document.querySelector('#board canvas');
const ctx = canvas.getContext('2d');

const { width: w, height: h } = canvas;

let rectW = 50;
let rectH = 50;
let x = w / 2 - rectW / 2;
let y = h / 2 - rectH / 2;
let color = 0;

function loop() {
// We need to call requestAnimationFrame again to tell it to run on the next refresh
requestAnimationFrame
(loop)
x += controls.x;
y += controls.y;

// We will be able to change the color with the action button
if (controls.action) {
color += 10;
if (color > 360) {
color -= 360;
}
}

// Set the color to black to 'clean' the screen
ctx.fillStyle = 'black'
// Paint it black!
ctx.fillRect(0, 0, w, h)

// Set the color using hsl (hue, saturation, lightness)
ctx.fillStyle = `hsl(${color}, 50%, 50%)`;
ctx.fillRect(x, y, 50, 50);
}

requestAnimationFrame(loop)

In this last version of our script file we are ready to go. The x and y values are centered at first but now are bound to the controls file. The color is set to 0 but can be changed by pressing the action button (check out to the CSS property hsl to know more).

You can now move the square around freely. Congratulations, you have created the most basic form of video game. It lacks everything you need to make it good, it’s not fun, it’s not pretty and it has no goal, but it’s where everything begins. And you made it by just writing a few lines of code. Congratulations!

Conclusion

It took a while to get here and what we have isn’t that great, but the purpose of this article wasn’t to make a good game. Since it’s part 1 of what will hopefully be a series of articles, I just wanted you to understand the fundamentals and I think we covered them all.

You should now be familiar with the concept of loop, with drawing each single frame to give the impression of animation and implementing controls. There’s a lot more to learn (we haven’t even touched collisions) but trust me when I say these are basic concepts that you will find in pretty much every single game out there.

I think it’s a good point to stop since everything that comes after is way too complicated to be done without using any module bundler and involves a lot of object oriented programming. I will do my best to explain how to import images and create a simple engine for a simple shooter next time.

Thanks for reading and stay tuned!

--

--