Inspiration
We wanted to build a game where the story is more than an excuse to shoot things. Both of our heroes have been hurt by people with power. Blue Arrow grew up as a nameless test subject, "Subject 7", in a sealed lab. Puff is a pufferfish whose ocean world was poisoned by corporations, and then picked by a bored alien civilization, the Directorate, as the setting for one of its cruel games. He won the trials and lost his home anyway.
Neither of them is a chosen-one warrior. They're survivors, and what makes them strong grows out of what happened to them. The experiments left Blue Arrow able to see with sound, and that's how she escapes. Puff's trials taught him to survive in the dirtiest water there is. Now they fly together with Earth Vanguard so that the same thing doesn't happen to Earth.
We also wanted the game to be playable by as many people as possible, so accessibility was part of the design from the start rather than something we tacked on at the end.
What it does
Earth Vanguard is a space shooter that runs in the browser. The Nyx Armada is dropping captive black holes on human worlds, and you fly the XF-9 Starlance with Puff riding along in a water bubble tethered to your jet.
- The main game: enemy waves, black holes that bend your lasers and the screen around them, escape-pod rescues, a radio choice, a choice about whether to trust Puff, and a boss that breaks apart in stages.
- Echo: a stealth game about Blue Arrow's escape. The facility is pitch dark, so every echo she sends lights up the walls for a moment, but the security drones can hear it too.
- Puff's Ocean: when a black hole tears Puff away, you relive his first trial. Get loud or hold the space bar to puff him up and float, go quiet or let go of the space bar to shrink and sink, and dodge ghost nets, oil spills, six-pack rings and garbage patches. Every game over shows a real ocean-pollution fact.
- Voiced cutscenes tell the story between missions.
Built for everyone
- Hands-free voice play: Puff's Ocean can be played with your voice alone. You make a sound to start and hum to swim again, so you never need a keyboard or a touch screen.
- Your voice, your range: the game tunes itself to each player. A soft hum works just as well as a shout.
- Privacy: the mic only measures loudness inside the page. Nothing is recorded or sent anywhere.
- Many ways to play: keyboard, gamepad or touch. On touch screens the jet follows your finger's motion, so your thumb never covers it.
- Adjustable text size (Normal, Large, Extra large) and a Skip minigames switch for players who just want the story.
- Any screen: the game becomes a side-scroller on a wide screen and a vertical shooter on a tall one, and switches when you rotate your phone.
- Local co-op: a friend can jump in at any time on the same keyboard or with a second gamepad.
- Representation: the main character is a young woman who turns what was done to her into the thing that sets her free.
How we built it
Everything is plain JavaScript, HTML canvas and the Web Audio API, with no frameworks, libraries or game engine. The source is about 38,000 lines across 37 numbered modules (input, audio, rendering, enemies, bosses, hazards, story, cutscenes and more). A small Python build script inlines all of them into one HTML file. All the art is drawn in code and all the sound effects and music are synthesized at runtime, so the game has no image or sound files and works offline when you double-click it.
- Black holes use a WebGL shader for gravitational lensing and fall back to a 2D canvas on devices without WebGL.
- Cutscenes are written as data in one script file, so the writers could change the story without touching the game code. The cutscene narration was generated with ElevenLabs.
- Voice control reads the microphone through the Web Audio
AnalyserNodeand works out the loudness of each frame in decibels:
$$ L_{\text{dB}} = 20 \log_{10}!\left(\sqrt{\tfrac{1}{N}\textstyle\sum_{i=1}^{N} x_i^2}\right) $$
To calibrate, the game records 2 seconds of silence and then your loudest comfortable sound. It takes the 60th percentile of the quiet samples as the noise floor $F$ and the 85th percentile of the loud samples as your peak $P$. From then on, how big Puff gets is
$$ k = \operatorname{clamp}!\left(\frac{L_{\text{dB}} - (F + 4)}{(P - 3) - (F + 4)},\ 0,\ 1\right) $$
so a quiet hummer and a loud shouter get the same full range of movement. If $P - F < 8\ \text{dB}$, Puff tells you he can't hear the difference and offers to switch to keys.
- Testing: we built a developer panel and URL switches to jump to any story point, boss or hazard, plus headless test tools that play the game and capture screenshots automatically.
Challenges we ran into
- Voice control that feels fair. Every voice and microphone is different, so one fixed loudness threshold can't work for everyone. Per-player calibration with percentiles, rather than an average or a maximum, keeps a cough or a background noise from throwing off the range. We also had to keep the game's own sound effects short and quiet in voice mode so the mic wouldn't mistake them for the player.
- Keeping it all in one file. With no image or sound assets, every jet, boss, wave and explosion had to be drawn or synthesized in code.
- Two orientations, one game. Making the same levels play correctly as both a side-scroller and a vertical shooter meant every enemy pattern, control and HUD element had to follow the screen's orientation.
- Connecting story and gameplay. We had to wire the cutscenes, voice lines, Echo and Puff's memory into the mission flow so the story plays at the right moments, without breaking the action in between.
Accomplishments that we're proud of
- A complete, playable story path, from the prologue through Echo, Mission 1-4, the black hole and Puff's memory, with voiced cutscenes.
- A minigame that people can play with no hands at all.
- A whole game, with its art, music and effects, inside a single HTML file and no external assets.
- Art is awesome in this game and we like it a lot,
What we learned
- How to synthesize sound and music with the Web Audio API, and how to read the microphone safely and privately in the browser.
- That accessibility features are often just good design: calibration, text size and touch controls made the game better for every player.
- How to split a large plain-JavaScript project into modules that four people could work on at once.
What's next for Earth Vanguard
The full five-mission campaign, four side stories, a hangar and skill tree, and the full radio cast are already designed in our game design doc. Three more bosses (Suneater, Mantis and Crucible) are built and playable in test sandboxes. Next, we want to connect them all into the campaign and finish Blue Arrow's and Puff's stories.
Built With
- canvas
- chrome-devtools-protocol
- css
- elevenlabs
- gamepad-api
- getusermedia
- git
- google-fonts
- html5
- javascript
- node.js
- python
- web-audio-api
- webgl
Log in or sign up for Devpost to join the conversation.