Ducks: Make a javascript game in just 30 minutes with the HTML5 canvas

Josh Weinstein
7 min readMay 3, 2021
Photo by Charu Chaturvedi on Unsplash

Quack! Want to learn how to create an interactive game with javascript, html, and a duck in less than half an hour ? If that’s the case, keep reading. Game development is a great way to enhance your programming skills and creativity at the same time. However, understanding where to start can be confusing, with so many different platforms, graphics libraries, and game engines available to use. To illustrate and comprehend the more fundamental aspects of a game and how graphics work, this guide will use a pure canvas object instead. By far the easiest canvas to use amongst the available choices is the HTML5 canvas. You already have a web browser if you are reading this, so you don’t need to download or install anything more.

Games: Evolving and Interactive Images

Most games are quite unique compared to other types of visual software. Images, and videos made by software are never changed after they are created. Whatever visual or auditory representation exists in say a video, will exist every time it is watched. Games, on the other hand, always display different behavior that is dependent on whatever interaction the a player has with a game. Instead of representing graphics in very stable, reusable formats, like .png or .mp4 , games draw graphics onto designated screen objects, like a canvas, very frequently. This frequency is also called the frames per second or frame rate. The goal of making any game at a high level is to create an internal state of elements and objects that the player can see and control.

To begin, let’s write up the backbone of an HTML page with just a canvas element in it. This game in particular will be about ducks swimming in a pond, so for the background, a light blue is used to represent water.

This file will serve as the for games code. Thus far, if you open this .html file in a web browser, you will see a light blue square centered on the screen. That’s the canvas, except, nothing is being drawn on it so far. In order for the game to draw on the canvas, it needs to be able to listen to input from a player. In Javascript, that’s accomplished through event listeners.

Events are Objects

In Javascript, events are objects that are emitted and then caught by a listener. Almost any action performed on a browser window can generate an event. Each listener only listens for specific types of events, such as a click, or pushing a key on the key board down. This game will be based off using the arrow keys to move our duck around, thus we are most interested in key up and key down events.

When an event listener “hears” an event, it passes the event object to a call back function. That call back can then execute whatever commands that are desired to change the state of the game. To abstract this player input from events in an efficient manner , the call back function we register as an event listener will change an object called a controller. This controller will track which, if any, of the four directional arrow keys are currently pressed down. Here’s our controller:

This controller object is registered with both the "keydown" and "keyup" events. The reason for this is later on, the goal is to check this controller to move the duck in the game. If there’s no key currently pressed down, the duck should stop moving. Otherwise, if one of left , right, up , or down is pressed, the duck should move in that direction. This controller is registered with the browser window with the following two calls:

window.addEventListener("keydown", controller.keyListener);
window.addEventListener("keyup", controller.keyListener);

Thus, the next step is to now implement our 🦆 friend, the duck.

Duck: The Game Element

The game implemented here allows moving a duck around a body of water. We can now check and read the input of a player using the arrows keys, but need to apply that input to the duck. The question is, how does a duck get drawn on the canvas ? In theory, it could be done through vector graphic commands, such as a path, arc, or series of lines. But that isn’t efficient for games. The internal objects of a game must be drawn at a very constant frequency, executing a bunch of stroke and fill commands on a canvas has a performance cost and limits the customization that can be achieved for characters. The best way to accomplish this for a 2D, top down game like this are sprites.

Sprites are visual representations of characters or elements with a finite range of positions. In 2D graphics, they are bitmaps that exist as part of the larger canvas. Typically, sprites have multiple image states to represent each direction of movement. Since we want our duck to be able to move in four directions, at a minimum, we will need four images, each one depicting the duck moving in a specific direction. To do this, I used a pixel art editor called pixilart . You can use any image editor or painting program for this though.

To make the duck small and more like a baby duck, I set him to be only 16x16 pixels. Here’s the four images :

The duck object in Javascript should follow a protocol for every time the top level draw function is called on the canvas to create the graphic of the game. For this example, we can use a simple protocol, with an action, destroy, and draw step. The “action” step is the part where we check the current input from the player and change our internal objects, like the duck internally. This accounts for changing the position of the duck on the canvas coordinate system, or changing it’s sprite image.

The destroy step isn’t used in this setup. But if it were, you would want a destroy function to be called if an object in the game should be removed and no longer appear on the canvas. This might be the case in fighting games where the player defats an NPC. Lastly, the draw step involves taking the state of the object and translating that state onto the canvas. For our duck, that just involves using the canvas context .drawImage(); method to put the sprite image on the canvas.

The above code represents the Image() objects used to contain the sprite images as well as the duck object, possessing an action, destroy, and draw method. Here, each movement statement such as this.y-- is contained within an if block. Each of these if statements check that the movement control coming from the player does not take the duck off the canvas perimeter. We don’t want our duck falling out of the water!

Putting it Altogether

Up to this point, we have went over the concept of events, their listeners, sprites, game objects, and drawing. The last, and final step, is to tie these elements together into a single graphic function that is called at certain frequency to readily paint the canvas. To do that, the overall state of our game, all of the objects, need to be sequestered into one single map, of the object name to the object body. Even though this particular game only has one object, it’s a good idea to understand code that can be used for more complex games with multiple objects.

The goal is that, the same protocol of actioning and drawing (with possible destruction) should be applied as if it were a polymorphic class or an interface across all game objects. We can encapsulate that logic into a function called drawGame like so:

Every time the drawGame function is called, we want to paint the canvas the background color to effectively wash away it’s previous state from the previous call. You may notice at the end of this snippet, there’s a call to the setInterval function. This is a native function in Javascript that calls some function passed to it every n milliseconds. 10 milliseconds in this case means 100 frames per second. You can adjust the frame rate to see the duck in the game move slower or faster.

Now, the moment you have been waiting for. Here’s a few screenshots from the finished product

Overall, the HTML5 canvas is a powerful graphics tool that can be used to create fun and exciting games. One of the best part is it requires almost no setup or installation, just a browser and a text editor! If you want the complete game and all the code we worked on, that’s below:

If you want to take this game or a similar one to the next level, consider the following improvement ideas:

  • Making an NPC that is controlled through an AI algorithm.
  • Add some sort of object the duck should collect, and a points tracker.

--

--

Josh Weinstein

I’m an engineer on a mission to write the fastest software in the world.