Back to Design Notes

Spare Knight: teaching the UI to explain itself

3 min read devlog ui phaser readability combat-design

Spare Knight shipped for Gamedev.js Jam 2026 with combat I was proud of and a UI I was not. The jam comments were kind but clear: the layout was hard to read, and a few players hit bugs that ended their runs. I replied “Game UI is not my forte, hopefully I’ll improve it in next builds” and then went and found out whether that was true. This update is the answer: a full UI overhaul, live now on itch and Wavedash.

Start with the font

The original build used IM Fell English everywhere. It looked like a medieval manuscript, which was the point, and it read like one too, which was the problem. Ability names, damage numbers, and tooltip text all paid the atmosphere tax. The overhaul swapped body text to Alegreya: still a warm serif that belongs in the world, but designed for reading. That one change did more for the game than any mechanic I tuned all jam.

A token system inside a game engine

The deeper fix was structural. Text styling was scattered across scenes as ad-hoc Phaser calls, so every fix had to be applied everywhere and drifted anyway. I rebuilt it the way I’d build a web app: a textStyle() helper with named type roles, PANEL chrome tokens for panel styling, and an atomic component kit (shared atoms, a real Modal) that every scene consumes. The first bug the migration caught was in the system itself: type role objects that never resolved. Once fixed, restyling all the non-combat scenes was a sweep, not a rewrite.

If you build design systems for the web, this is the same discipline in a different renderer. Tokens are tokens.

Make the mechanics visible

The combat rules were always deterministic; the interface just kept that a secret. The readability pass made the game state legible on the grid itself:

  • Enemies are highlighted directly, with their threat range shown, instead of asking you to decode cell tints.
  • Every status effect now renders on-grid, and its tooltip is derived from the actual mechanics data, so the text can’t drift from the rules.
  • Ability buttons know why they’re disabled. Out-of-range abilities stay armable, and a reason tooltip tells you what’s wrong instead of just graying out.
  • MP costs sit on the buttons as price tags, damage numbers are signed, and hits land with real collision and an impact bounce.

The lesson repeats from my ThunderBashers postmortem: readability is a mechanic. Deterministic combat only feels fair when the player can see the determinism.

The soft-locks

Two players reported turns that never ended. Both traced to the reaction system: a timing wheel could wedge in a state that never resolved, and separately, killing the turn announcer tween mid-flight left the turn queue waiting forever. Both were root-caused and fixed, along with a combat input crash from a stale text pool and an invisible-cursor bug that the new painterly cursors replaced outright.

What carried

The whole overhaul landed as one feature branch, built module by module in seven passes: typography, tooltips, ability bar, statuses, inventory counts, panel chrome, scene migration. Fixes first, then polish (fullscreen mode, cursor sweep, a Salvage and Forge layout rebuild with aligned panels). Player comments picked the target; the token system made hitting it cheap. The next build gets content instead of apologies.

Let's build something.

chrisdalbano12@gmail.com

© 2026 Christian D'Albano · Hand-built design system — Nuxt 4, Tailwind, motion-v. Tokens and motion vocabulary by me.