Building A Canvas Game Engine / Framework From Scratch

Chang Yan
6 min readDec 7, 2017

--

Foreword

A few months ago, I built a Tetris game with React and Redux. This semester I was enrolled in the course CSC591 Game Engine Development. Previously I’ve been working with Front-End development, but the experience with game design has really taught me a lot. At the end of the semester, I released my own canvas game engine / framework, Zion, and a few game demos built on top of it. So I’d like to write a post on game (engine) development, to share some knowledge of what I’ve learned along the way.

What Makes A Game Engine

Let’s think about what are the features that most games share in common. Generally, they have a scene that is displayed on the screen (graphics / rendering). Some have advanced rendering techniques (particle system) to render smoke, fog, etc. You could interact with the game with mouse or keyboard and have sound(I/O). Some of the games have bots(AI) like WarCraft 3. And also they support multi-player online to play online (network) at the same time, like Counter-Strike Source, etc.

You might still continue coming up with more and more features. And now you are already getting much closer to the core of the game engine. A game engine is to provide a set of the abstracted utilities to implement the features we talked in the last paragraph. It is a comprehensive building environment written in a specific programming language. It’s everything that is NOT specific to a particular game.

To get even closer to it, this game development roadmap might help you to understand, from basic to advanced: Bare Metal (Game Arduino) => Operating Systems (Windows)=> Libraries => Frameworks (PyGame)=> Game Engines (Unity3D)=> Makers => Wizards.

Before Writing Code: Thinking

You might have already written some code with canvas. It’s brought to life and widely used thanks to HTML5. The good thing about that is that you don’t have to build everything from scratch because canvas itself is already giving out some APIs for you to build a game. So it’s different from building GUI interfaces for everything like Unity3D with C++ from scratch.

However, speaking of which, the canvas has provided abundant API, but it’s far more than enough or complete, for the following reasons:

  1. The APIs are rather a bunch of scattered utilities. And function utilities are too flexible in that they don’t provide a typical flow or confinement of how the games operate.
  2. The canvas APIs don’t give you enough abstraction. Say you want to draw a rotated sprite, you would possibly write more than 10 lines of codes with the combination of several APIs. And it’s gonna take you to write 5 lines of code to draw a line. That’s counter-intuitive, why can’t things be easy??
  3. It’s a pain to mind browser-features, DOM features and canvas ones at the same time. For example, in I/O you need features other than from canvas, like DOM Event.

Considering all the above and potential reasons, building a canvas engine / framework is more like combining all the scattered concerns, consecutively build utilities for consumption of our game and fixing the bug-prone issues, while hiding the implementation details.

At first, you might wrap up some functionalities that provide higher level of abstraction on top of canvas APIs, like, drawLine(), which is great to start with. But at this point, you are actually building a library, not an engine. A framework can of course contain a set of library-like utilities. But to make a real engine / framework, you really need to put effort in thinking about how to deal with modularization, the interface design, and mostly importantly, what is the game flow and how to “get framework call your code”.

Luckily, I got quite some ideas from the lectures and by doing the assignments. To put it straight, let’s think of a game as a infinite state machine. (This borrows the idea from JSON and Redux.) Everything is stored in a big JSON object and your interaction with the game is just modifying the state tree.

So the game is all about “updating state” and “rendering the state”. And with these two things wrapped with a timer like “setInterval”, the game structure is all done, like what is shown below. And in Zion, we provide a base class called Game for class-based extension. This is the start point, also the confinement that Zion provides with game flow.

I got quite inspired from the design philosophy of Redux. Because if we think of a game a state machine, then redux could be a perfect choice as a state manager. The good thing is that Redux itself is not framework-specific, so you don’t need anything else to use it in your project. The advantage is that the change of the game state becomes more manageable and easy to track or to debug, while the tradeoff is that the amount of code has to increase significantly, and most of the time it doesn’t make that much sense to bring it in. So I didn’t incorporate it with Zion, in case it becomes too opinionated.

Get Your Hands Dirty

Building a framework requires a good understanding of some design patterns, modularization, etc. The good thing is that if you already have some knowledge and experience with JavaScript or Front-End development, you don’t have to spare extraneous concerns about the syntax or language fuss. That gave me enough energy to focus on the GAME itself, rather than got distracted by the quirky parts of JavaScript, etc.

The basic idea is to add a more abstraction layer of each feature to the game engine, on top of the browser APIs. I’m not gonna dive deep into the implementation details because you can always check the source code and the document of Zion here. Here I want to talk about some lessons I’ve learned along the way of building Zion.

I personally think the ideal scenario to build a tool is like this: You first come across a problem / issue. You do some research, whether on StackOverflow or Github, etc. And you abstract the solution with a standalone library or utility.

Zion is exactly built this way. We didn’t first build the engine, but started out with the target of implementing a drag and drop game. To implement the DnD in canvas, I combine a few event listeners and added the DnD component to Zion. In this way, after building five games, Zion has become a framework that has almost all components that a typical game framework should have.

Another more specific example is the flickering issue during rendering. I came across this issue in the third game. Every time when you call render, if you create too many images instance all over again from scratch, it leaves you with a time gap where before the images have been all loaded, the canvas is blank. And this makes the screen flickering drastically. I got the idea of solution from https://stackoverflow.com/questions/17261080/html5-canvas-blinking-on-drawing. But it doesn’t provide me with good abstraction, nor clean code. So I built a standalone promise-based utility canvas-image-cache myself, which was later on added to Zion. Another similar example is the KeyBus, which deals with the simultaneous keyboard handlers.

So the thing that I learned is that you don’t build some stuff which is perfect at the beginning. I recall from a blog post I’ve read earlier that says, “If you wait to release until you feel your product is good enough, then it’s already too late.” The same goes with your application. It’s totally okay that it’s shabby and incomplete at first. Rome is not built in a day, and software needs iterating. Even React, which has a bunch of full-time maintainers and more than a thousand active contributors, is receiving bug reports and arising issues every single day. It’s the iteration that makes good software better, and stand out.

So this is probably the reason I’m releasing the first version (v0.1.0) of Zion. We finished its document a few days ago, and during this process I’ve been reflecting a lot, about what makes a good, friendly interface design and have learned quite some. We have already built five game demos on top of it, which proved it had a good start. And now I want more iterations and to listen to your opinion on how to make it better.

If you love open source, do not miss this chance to participate in this unexploited area. Issues, bug reports, pull requests, suggestions are all welcomed!

Reference

The Game Spectrum, Adam M. Smith, UC Santa Cruz

Zion — A tentative, light-weight 2D game framework based on HTML5 canvas. Support rendering, I/O, network, AI, etc.

--

--

Chang Yan

Front-end engineer at Meta / Content-creator / youtube/c/changyan