Archive:
Super busy month, again – who knew day-jobs would suck up the time I'd normally be sat in my pants, making stupid jokes to amuse myself – but I have snuck the odd bit of time in to do more EH500 hacking. Mainly because I can’t run Unreal Engine on my laptop, so this is about the only thing I can do when I have the odd hour on the sofa…
All of these are external libs, they’re not part of the actual “fantasy console”. They’re bits I can drop into games, as and when I need them.
Quick win, this one. I've added a GIF recorder. Hit F10, and it starts capturing frames; hit it again, and it spits out a timestamped file. There's a pulsing "REC" indicator in the corner, so I don't forget it's running, and because it makes me laugh.
Why bother? Honestly, I’ve always wanted this in my games. Having to faff about with OBS or screen recording tools every time I want to share a clip is boring. Now I can grab gameplay snippets for bug reports, social media, or just to remind myself what something looked like before I inevitably break it. Whee!
This one's been brewing for a while. My test game was littered with raw SDL input checks – keyboard here, gamepad there, mouse somewhere else. It was getting messy, and I knew it'd only get worse as I added more features. The engine does have an input abstraction, but it's hardcoded to joypad and WSAD, and I just KNOW someone will want to redefine keys...
So I've built a proper input binding system. Define an action once ("Jump", "Dash", "Interact", whatever), bind it to keys, buttons, or joypad axis, then query the action anywhere in the code. Doesn't care if the player's using a keyboard, or a DualSense or something exotic – the game just asks "is Jump pressed?" and gets an answer.
I've shamelessly nicked the design philosophy from Unreal's Enhanced Input system. Contexts, modifiers, triggers – the works. It's probably over-engineered for what I need, but it’s familiar, it means I can support rebinding, multiple input devices, and all that quality-of-life stuff without revisiting it later. And honestly, it just makes the gameplay code soooo much cleaner.
Right, this is the one I'm most chuffed about. Blame Lumo 2, where I fell in love with Gameplay Tags over the course of development.
You know how games end up with a million boolean flags? bIsDead, bIsInvulnerable, bIsDashing, bCanInteract, bHasDoubleJump... it spirals out of control fast. Every new feature adds more flags, and the logic to manage them becomes a tangled mess of if-statements.
Gameplay Tags to the rescue. Instead of flags, entities have a set of hierarchical tags. Something like Status.Alive, Ability.Dash.Ready, Buff.Invulnerable. The hierarchy means I can query broadly ("does this entity have any Status tag?") or specifically ("is Ability.Dash.Ready present?"). And because it's all done with bitsets, under the hood, it's reasonably fast.
Back on Lumo 2, I started using Unreal's Gameplay Tags for AI queries. Bog simple, stupidly useful. Then I added them for teleporter detection. Then for blocking actions when carrying items. Then for spawning VFX. Each time I reached for them, they just worked and then I kept finding new uses.
But here's the thing I learned the hard way: you have to commit to them. Early on, I layered tags on top of an existing state machine, and ended up with race conditions falling through the cracks. I spent more time than I'd like to admit debugging animation blueprint issues that wouldn't have existed if I'd driven everything through tags from the start.
Eventually, about a year into development, I refactored the entire character controller to be tag-driven which was an incredibly stupid thing to do that late in the project. But the result was so much cleaner that I wished I'd done it sooner. The moral: if you're going to use tags, use tags. Don't half-arse it.
And yeah, I’ve added callbacks to the Tag container, so I can register functions that fire when a tag is added or removed. Instead of polling "is the player dead?" every frame, I just hook into Status.Dead being added, and react immediately. Systems become reactive rather than constantly checking. It's tidy, and it scales. Kinda like a simple message bus.
Triggers are zones that I defin in Tiled that do things when the player overlaps them. "Things" being: add or remove gameplay tags. :D
The beauty of this is that it moves game logic out of code and into the level editor. Want a checkpoint? Drop a trigger, configure it to add Checkpoint.Whatever. Want a hazard zone? Trigger that adds Status.OwOwOw. Etc.
The trigger system just reads the zones from the Tiled map, monitors for overlaps, and fires the appropriate tag changes. The rest of the game reacts through the callback system. It's designer-friendly, and it means I can experiment with level flow without touching a line of code.
These four systems might seem disconnected, but they slot together nicely. Input Actions give me cleaner control queries. Gameplay Tags form the foundation for the way I build things now. And triggers are triggers. Every game’s got a trigger. And I’m happy because that’s most of the scaffolding in place.
Annnd boring admin work: I've moved the Triple Eh? website off Squarespace. Nothing against them specifically, apart from their price, but with America turning into a bit of a bin fire, I'd rather not have my business related guff sat over there. It's now hosted on an EU server, and it's just plain HTML, CSS, and JavaScript. Cheaper, and less faff.
Host all the things, yo.
Musings, random thoughts, work in progress screenshots, and occasional swears at Unreal Engine's lack of documentation -- this is a rare insight into what happens when a supposedly professional game developer plans very little up-front, and instead follows where the jokes lead them.
Journal IndexFriends:
If you like any of my work, please consider checking out some of the fantastic games made by the following super talented people: