Game ProjectsPortfolioWeb

Creating a JavaScript Game

Concept to Release


In 2013 I was involved in a conversation about updating an academic website called Ukraine Alive; a website that was designed to teach people about the Ukraine. The professor in charge of the project learned that the study of the Ukraine, along with other countries(China, India, Tunisia, and Peru) was part of the Alberta Social Studies elementary school curriculum. They wanted to modify their site to make it more approachable by young students.

It was mentioned that games could really help with this. The usual educational style of games were proposed: Coloring pictures, puzzles, and ordering cards; and eventually implemented. These we’re all great ideas, but I was hoping to do a lot more.

I went back to my office and started developing a prototype. I already knew a bit about developing animations using JavaScript and figured I could do a lot with  a 2D top down style. I modeled a map roughly around the Ukrainian Village not far from Edmonton and made some rough 2d sprites and tiles(modeled after Super Nintendo era graphics).

This was enough to impress those involved in the project, and planning started right away for a fully functional game.

Prototype Demo: http://markmckellar.com/HTML5/Ukrainian/index.html

Initial Game

The original plan was to have a game to work similar to a Massive Multiplayer Online(MMO) Role Playing Game(RPG) where students of a specific classroom would have access to their own village. In this village, each student would have access to their own house. They could furnish their house by completing tasks around the village that related to Ukrainian culture. On top of this, each house would have its own Domovoy; a house spirit in Ukrainian folklore that will cause mischief around the house if it was not kept clean or newly furnished.

JavaScript, along with WebGL, was used to produce the front facing web application, and C# MVC, with the use of Websockets, was used for the backend. I was responsible for the front end application, while another developer created the back end.

From here we produced a demo that could allow multiple users to connect to a village using an access code; walk around the village; see other students; and paint a Ukrainian Easter Egg.

Student Involvement

In 2014, four student students from a MLCS(Modern Languages and Cultural Studies) course were asked to join the project where they would create the game stories, provide artwork, and design game components. Through the involvement of such an enthusiastic team, the games really began to take shape. They helped to steer the project away from a MMO style game to a more streamlined story driven adventure. The story would focus around the respective countries folklore.

The Ukrainian game would focus on the story of Baba Yaga, a type of witch in slavic cultures who would implement a curse children in order to teach them a lesson. This story would involve a child who was cursed by being turned into some sort of animal(most likely a pig), and had to help people around the village in order to reverse the curse.

Another story was created around Chinese culture. This story would follow a child who was blessed with a magical paintbrush, which would make anything they painted a reality. They then had to use this to help others.

At the end of school year, we were able to present the results of their hard work at Edmonton’s GDK 2015 event.

Game Discovery Exhibition
From left to right: Mark McKellar, Jiwon You, Don Nicholas, Natalie Kononenko, and Peter Holloway.

Over the next four years, eight students were involved in the project; each providing unique content and additions to the game engine. The Ukrainian game was temporarily dropped in order to focus purely on the Chinese culture game.

The engine was completely rebuilt in order to facilitate student involvement where they were not only designing assets for the game, but implementing them as well.

We decided to use Tiled(https://www.mapeditor.org/) as our map editor. It was flexible enough to handle our are, and allowed us to write our scripts directly onto components within the game.

Students could also add dialog to a CSV file, which could then be called within the scripts to initiate conversations. They could also add sprites simply adding JavaScript files describing the sprites location and animations.

Painting tasks were created to revolve that focused one items important to historical china. A stealth component was also included to help break up the activities within the game and provide a unique challenge.

Finally, a minimap was also requested by the students. Maps became larger and more complex, and having this helped to provide direction.

This was the first time I led a team of constantly changing team members. It required managing individuals with completely different skill sets in order to produce a single result. I learned a lot about time management, curation of ideas, and when and where to maintain expectations.

Weekly development planning.

Last year the implementation for the China Alive game was released a tested among students. Anonymous information was obtained using Google Analytics which described when users performed tasks, which characters they would talk to, and how long it took them to complete the game.

Since then, bug fixes and minor enhancements have been the focus.

Current Implementation: http://chinaalive.ualberta.ca/wp-content/iframes/VillageGameLocal/China/

Technical Details

Source code can be found here: https://github.com/arcualberta/VillageGameLocal

The Engine

The game engine is built using JavaScript, Html 5, and WebGL(WebGL 2 if the browser supports it). The system works by having three main types of classes: adapters, event objects, and actions.

Adapters are used to provide this functional bases for the game engine. Modules used for this game are audio, display, control, physics, map input/output and the dialog system. The modules can be swapped out based on the capabilities of the browser and device being used. For example, the display modules first checks if the browser supports WebGL 2; if it does not, then it will fail over to a WebGL based module; and finally, a regular 2d canvas based adapter if needed.

Event Objects are objects that can have events attached to them. The events could be frame ticks, drawing, click actions, or if a character has interacted with them. Everything within the game including maps, sprites, menus, minigames, and triggers are event objects. The drawing is an event, not all event objects need to react to this event; therefore, not all event objects must be drawn. Event objects can also contain child Event objects; this allows for events to be recursively triggered on the child objects.

Actions are a set of rules place on an Event Object to tell it what to do during an event. Actions can include moving the camera, moving objects, playing different sounds. Many actions are precoded in the game, and can be called by objects, but designers can also create custom actions on events within the Tiled Map Editor. These scripts are pure JavaScript and have access to the current object and the map.

Tiled Map Editor

The Game Loop

Just like most games, the majority of the work happens between each frame and is used to calculate the next frame and then draws it. This is done over and over again, until the users has left the game. Here is the general loop for this game:

  1. Request the browser to trigger the loop event next time the JavaScript interpreter is free to draw a frame.
  2. Read all of the controller events.
  3. Perform any click events that were recorded.
  4. If any menus are displayed perform the “tick” event on them.
  5. If the game is not in the “Paused” state:
    1. For all objects currently alive in the scene, perform the “tick” event.
    2. If any objects have collided with other objects, perform the “interacted” event.
      • One event that is a subcategory of the “interacted” event is the “talk” event. This happens when the player initiates a conversation with the object.
  6. Perform the “tick” event on the Heads Up Display (HUD)
  7. Calculate the drawable portion of the map.
  8. Calculate any objects that are currently visible.
  9. Draw all visible tiles below the object layer.
  10. Draw all visible objects.
  11. Draw all visible tiles above the object layer.
  12. Draw the the HUD.
The ChinaAlive game running in debug mode.

Drawing and the Trouble With Arrays

Within this application, drawing each frame is the most computationally expensive aspect. We must calculate what is visible to the player, and only draw what is necessary.

Calculating what is visible to the player begins when we first load the scene. Each map has multiple layers which can contain either tiles or objects. Each of these contain information about their location on the map and their size. Once loaded, we store all of the information for a layer using a Quad tree data structure. Each node on the quad-tree recursively contains exactly four mutually exclusive area nodes contained with this parent.  This allows us to create an easily searchable tree to store these drawable items based on their containing area within the map.

Each frame we search this quad-tree for all elements within the visible area of the camera. For every drawable element found, we add this to an array that will eventually be sent to the Display Adapter for drawing.

At this point an extremely large bottleneck can occur. The creation and maintenance of arrays are extremely expensive in JavaScript. This is because, in JavaScript, Arrays work more like Lists or Map structures. Their data is not stored within a clump of memory, but split among several locations and is only allocated at both the start and whenever new elements are pushed onto the array. These arrays must also handle any type of data this could be both primitive or complex type of objects. On top of all of this, JavaScript is an interpretive language meaning that the machine must first parse human readable language, change it to instructions it can understand, then execute them.

When initially drawing the maps, depending on how many layers and objects were used, the frames per second(FPS) could slow to even the single digits. To help solve this, in both the drawing functions and anywhere else in the code that this may pop up, the following rules were used:

  1. Whenever possible reuse arrays.
  2. If it’s needed to clear the array, do the following “array.length = 0”
    1. Keep all the memory allocated for the array, making it quicker to add new items.
    2. One thing to note, in most browsers this means that all objects in the array are still being referenced until they are overwritten, so garbage collection will not free this memory until then.
  3. Whenever possible use “Typed” arrays.
    1. This are arrays that only accept specific primitive types(such as floats or uints).
    2. Usually browsers contain low level support for these arrays making them much faster.

By implementing these tweeks, it was possible to have the game run at 60FPS on most desktop systems and 30FPS on most mobile. Because of this, the game was set to run at 30FPS.

The MiniMap

The minimap

It turned out that this method was very expensive, and dropped the frame rate dramatically; even on powerful desktop machines. It was essentially doing the most computationally expensive aspect of the draw call, but with a larger area.

One aspect that was requested late in the project’s life cycle was to include a map in top right corner of the screen. This map would show a slightly larger area than what’s visible to the player, and would update dynamically. To do this, may of the same aspects for the drawing loop were used; such as finding what tiles were visible within this area. When it came to drawing, each tile was assigned a specific colour and drawn to a texture as a single pixel. This was then drawn to the screen.

To solve this, I implemented a method that would update only a quarter of the map with each frame. The first frame would update the upper left corner of the map; the next frame the upper right; then the bottom right; then finally the bottom left.

This solution proved to work quite well and was difficult to notice; unless you were looking for it.

Threading Using Web Workers

JavaScript provides a controlled form of threading through a system known as Web Workers. These workers perform tasks outside the main thread and can be used to perform tasks that don’t directly interact with the web browser.

The initial system calculated the visible area for the map using these web workers. They would contain all of the information of the maps and provide the main thread with all of the visible elements.

This ended up being highly inefficient. The worker was called at the beginning of the frame by passing in the current map state. It would then provide the needed tiles by the end of the frame in order to draw them. This thread had to return these elements due to the fact that these workers were restricted from drawing anything to the screen. Because of this, the process of sending the data back and forth between main thread and the worker cost more than just doing these calculations on the main thread. Due to this, web workers were abandoned.

What am I proud of?

This project has been a passion project of mine for almost six years. In that time I found a lot to be proud of. I was able to produce a concept, see it evolve with input and hard work from others, and eventually become a fully functional game. I learned how to manage teams of ever changing individuals and tasks. Most importantly I was able to meet and work with some highly talented individuals, who still surprise me with the quality of work they produce.

Demo: http://markmckellar.com/HTML5/VillageGameLocal/China/index.html