Creating a Web App Game Series: A breakdown / write-up of the project (+ source code)

Jared Stanley
7 min readMay 7, 2020

The Initial Idea

Back in October I read an article with Rob Ford of FWA which talks about how overall creativity on the web today is lacking when compared to 10 years ago, back when Flash was popular and before algorithmic marketing.
While I don’t agree with everything written there, the article did inspire me to build something just for the fun of it.

I wanted to create some very passive games with very light interactions; use minimal instruction and have the gameplay be discoverable and quickly discernable.

Live Url

Play it here: Live URL

Github Source Files

Get the code here: Source Files

Visual Design + UX

I wanted the games to be challenging but not frustrating. The first games in the series would be dead-simple to pass, strengthening the users’ resolve to continue as the games became more challenging.

I started with some comps of game ideas:

The initial comps for the game series.

I initially wanted a monochromatic, consistent color palette throughout the games; I ended up with a unique palette for each game.
I wanted each game to have a small instruction animation showing game play for that game.

Building the App

Most of the games could be built in Javascript using the HTML5 Canvas Drawing API.
Some games required more complexity like utilizing the WebAudio API or DeviceMotionEvent for accelerometer data, or webGL (Using three.js) for 3D functionality.
I planned to tackle the less-complex games first before building the more challenging ones.

Overall Structure

I created a controller to load/unload the different sections, and included the model(which is really simple, just a list of the different games as objects). Then I built universal UI elements like the progress bar etc.

Once this general structure was in place I created an abstract ‘Section’ Class that could handle instantiation and deletion; I then extended that Class for each of the game chapters.

For the setup I used NPM and WebPack as the module bundler, and I tried using ES6 (+Babel) where possible.

For universal elements (like the progress bar) I used one instance, updating the color scheme when the user progressed.

One single component, updated with different color values.

Reusable Components

Throughout the build I would create some bit of functionality, then refactor that into encapsulated components. Then I‘d abstract these components further to be reusable.
Things like the timer bar, the Bubble Class, the Audio Manager to generate the tones, etc were reused across multiple games.

One component reused in different instances: The top timer bar grows from the center, the bottom one shrinks from the right..different functionality with the exact same code.

Abstracting User Events

Mouse and touch events would all pretty much do the same thing (I wasn’t adding dragging, multi-touch or anything beyond basic clicks); I was able to abstract these out into the parent Section Class by binding the event to the clicked element; I was able to create and destroy these cleanly.

Avoiding Libraries

I liked the idea of using vanilla js where possible; I tried to not use libraries where I could. Things like the animation of the progress bar are simple with a library like GSAP, but I really just needed a small bit of the functionality:

function growTheBar(itm){
iteration++;
if (iteration < totalIterations) {
h = tweenFunctions.easeOutSine(iteration, curH, itm.height, totalIterations);
curH = h;
}else{
iteration=0;
needsUpdate=false;
dir="shrink";
}
}function shrinkTheBar(itm){
iteration++;
if (iteration < totalIterations) {
h = tweenFunctions.easeInSine(iteration, curH, 0, totalIterations);
curH = h;
}else{
iteration=0;
dir="grow";
}
}

BTW this approach uses Robert Penner’s Easing equations.

Avoiding libraries turned into avoiding lots of technologies and questioning the idea of building autonomously in a vacuum (which btw is ridiculous and impossible and the subject of a future post).

Animating with Lottie

Along the way I ended up changing the flow to feature an intro svg more prominently at the beginning of each game chapter.

Each animation is based on something personal to me and my interests (I grew up in the red desert, I paraglide, etc).

I created an svg animation for each game in Illustrator and had each svg+corresponding game share a color palette:

Color Palettes for the respective chapters.

After Effects for the Web

After Effects is an industry-standard motion graphics tool and primarily used to export to video.

I created the animations in After Effects, then used BodyMovin to export to a .json file. Then I used Lottie to control the svg animation (pausing during transitions, when off-screen, etc).

To create dynamic animations that play nicely with Javascript the animation needs to be built correctly: blend modes, effects, masks etc only work if set up properly; many features aren’t supported and don’t work at all.

Game Screenshots:

First Chapter — Just tap once and proceed to Chapter Two. This is designed to give the user a high interaction:reward ratio so they won’t give up when things get more difficult.
Chapter Two — self-explanatory, just tap the bubbles to pop them. Very easy.
Chapter 3 gets significantly more difficult: Tap to start the timer and then try to tap again before the timer runs out; rather tap it right exactly as the timer runs out (within a 0.1sec tolerance).
For chapter 4 some musical knowledge helps; however even without this the user can figure out which notes highlight the words at the bottom.
Chapter 5 is like Simon: the computer plays a random sequence of notes, you have to repeat the same sequence. It begins with one note and progresses to a sequence of 6 notes.
Chapter Six: Tap to start a timer, then choose a box before the timer runs out. The computer reveals its choice when the timer expires; the objective is to guess which box the computer’s going to choose.
This is a ‘coming soon’ screen that lets the user continue to interact; The game is reused from a previous chapter, but with many more/smaller bubbles. When you pop them all a brand new set comes in.

Challenges

I ran into some snags along the way:

canvas.getContext()

For one of the games I wanted to display a .glTF 3D model; I’d built everything up to this point with canvas 2d context, but for this I’d need a different context that could handle 3d. I learned that you can’t change the context of a canvas once it’s defined.
To solve this I built a canvas switcher, which just swapped two divs containing a <canvas> element with “2d” and “webgl2” contexts respectively. It’s still in there but I ended up scrapping that game and didn’t end up needing this.

DeviceMotionEvent

Another game that I had planned used accelerometer data; I’ve done this before so I wasn’t concerned about the implementation.
Unfortunately for me Apple decided having this data accessible by default was a security risk so they shut it off in iOS12; turning it on required the user to go into the settings.
Then in iOS13 they changed it to a permission request, similar to how the GPS or Camera are accessed.
This introduced a ton of complexity and frustration. I was going for simplicity so I decided to abort this functionality and come up with a different game…one of the perks of a personal project!

Testing

As more games were added, play-testing the games and progressing to the specific game I was working on became tedious. I’d have to pass each level before proceeding to the next — very annoying when working on multiple levels.
Naturally, I tried to move the game’s position to the first slot. Unfortunately to save time I hard-coded the intro into the first game, so to get this to work required some refactoring. Instead I created a config object that let me quickly skip through the games.

Interest

Another snag I hit was real life. Family obligations, work projects, etc as well as new ideas to build popped up and this project fell by the wayside.

Like most personal projects, this started off with a flurry of activity and momentum and then fizzled out after that (see commit history). Getting projects over the finish line is a challenge as interest in the project fades.
I only had few more hours of work left to ship this; with Covid-19-induced WFH happening I was determined to do so even if it wasn’t in the state I’d envisioned.

Summary

This was a great exercise to challenge both my interaction design + development skills. I’m fascinated by both design and development and love that the tooling today allows us to touch a lot of different parts of a project.

It was fun to work on a project with no other business objective than to just provide a small amount of entertainment. There’s still a ton of rough edges but I’m glad it’s out in the world; this gives me the freedom to focus on new projects and then come back to this if I ever decide to.

--

--