2026-03-01
I built the software side of my alt-control game, Nuclear Logistics Bureau's Typing Challenge, as a website. Rather than use a game engine like Godot, or Love2D, or even Phaser, I used React.
Why.
Yes, very valid question.
- Game engines don't really handle typing input easily. Web browsers are built for it.
- There's no player, no graphics, no physics. Everything on screen is meant to simulate an ancient computer terminal. Would would using a game engine give me? I thought about using, say, Twine, because my game is essentially branching text nodes, but I don't think Twine is set up to handle typing input either. Rather than try to learn a new tool that may or may not do what I wanted, I figured it would be easier to just use the tech I know. And the biggest reason:
- After being out of work for a few months, I start a new job as a front end engineer soon and I thought this would be a great way to derust.
And I think it was!
Some notes about the structure
- This game is a bit like a piece of interactive fiction (see my internal debate about using Twine above): there's a prompt on the screen, the player types a response, and a new prompt appears based on that response. That's not solely how it goes; you can play tic tac toe (the CPU is real dumb, like dumb as rocks), and you can play the eponymous typing challenge, and those both have a bit more complicated state. Oh, and there's sometimes (usually) a countdown timer. There are 8 possible endings.
There weren't THAT many nodes (65), I kept all the prompts in one dictionary of PromptID: {Prompt}.
type Prompt = {
text: string;
time: number; //seconds until timeout, or -1 if infinite
gotos: Object; // ok I didn't name this great. But it's an object where the keys are responses and values are the prompt IDs those responses lead to. For example, {"y": 5, "n": 6}.
on_unknown: number; // a prompt ID. If you type anything not in "gotos", or if your timer runs out, this is where you go next
ending_number?: number; // if this is truthy, the program knows the game is over
};
- I used a Context + reducer pattern and probably 3/4 of the whole game lives in the reducer. This was one thousand percent the right way to build this. Highly recommend if you're doing something similar. I only ended up needing 4 actions, which feels kinda wild.
export enum ACTIONS {
END_CPU_TURN, //when playing tic tac toe. After the player makes a move, the CPU has to "think" a minute and make its move before returing control to the player
KEY_INPUT, //dealing with key input was kinda gnarly. Yeah, even after I said all that nice stuff about web browsers. It's because I was doing silly things like silently collecting input until I got a string of length 5, then mapping that input to my ridiculous 5-bit-pseudo-ASCII, oh but also there's a shift key
PROCESSING_COMPLETE, //after the player types enter, a "processing" "animation" plays, and when it's over, the reducer has to figure out where the player goes next
TIME_UP, //signaling the reducer to go ahead and move on when the player doesn't hit enter before the timer reaches 0
}
Some things I learned
-
The Web Audio API can generate sounds programmatically. It felt a bit like making SFX in Pico-8, except in JavaScript. Like, you can configure it to play at a frequency, for a duration, using a certain kind of wave, and the web browser will happily beep and boop at you! I had no idea. This is not really the kind of thing that's useful at my day job. It's also probably not a great way to write a soundtrack, but all I wanted was to emit vintage-sounding error beeps, and this was absolutely perfect for that.
-
The browser also has an API for text to speech! I had no idea. I seriously thought about using it, you know, to really drive home the War Games aesthetic, but I ended up cutting it. Mostly I didn't want to spend time and effort wiring it up for a game that's meant to be played in a showcase/arcade environment, where it's hard to hear anything at all.
-
It is shockingly easy to create a "good enough" CRT effect in CSS. No scanlines, but I don't think they're necessary. All you do is add a reddish shadow to one side of the text and a bluish shadow to the other side of the text. It's just enough to make it look a little blurry. (My eyeglasses do the same thing. Please tell me I'm not the only one who sees this.) I normally think green or amber when I think of old monitors (amber monitors my beloved), but cyan is what they used in War Games.
body {
background: #1b1b1b; /* black */
text-shadow:
-2px 0px 2px #db7497, /* pink */
2px 0px 2px #41bcbc; /* this is kind of a windows 95 background teal */
color: #5fe4e4; /* cyan */
}
I should maybe specify that I wasn't trying to make a game about the movie War Games, I just wanted to borrow the vibes.
But is the game actually fun?
Unknown. It'll have its first real playtesters at the showcase event next week. But I think it at least has the potential to be fun!