stealth puzzle programmer

Crush the Hero

image coming soon key art

ABOUT THIS PROJECT

A turn-based stealth puzzle where you help the demon, not the hero.

You are the demon princess, tired of blind dates, and your father has just captured a charming and extremely gullible hero. The twist is that you never control him directly: You solve the puzzles, dodge his attacks, and rearrange the tower so he walks himself to safety. Built in Scala on LibGDX with Matchmaker Studios, an eight-person team, for Cornell's introduction to game architecture course, and shown in the Desktop division of the 2026 GDIAC showcase.

Turns run through one state machine

Wired the level onto a turn FSM: WaitingForInput hands to DemonTurn, then HeroTurn1 and HeroTurn2 with a timed Wait state before each, and Fast variants that carry the propagated input so holding a key skips the waits instead of queueing them. Win and lose are two flags that collisions set during a turn and the scene reads only once the turn has finished animating, so the hero always completes his step before the level judges it, and a spike and the goal on the same turn cannot both fire.

image coming soon a turn resolving

Priority-based line of sight

On each turn he casts along all four directions and takes back the first entity seen, its distance, and the mirrors the sightline passed through. Each candidate is scored by getPriority, the highest wins, and ties are broken by the shortest distance so he commits to the nearer of two equal targets. Looking back along his own facing is flagged as sound rather than sight, using the dot product of the cast direction against his facing, so what he can hear behind him and what he can see ahead are handled separately.

image coming soon sightlines

Making his reasoning visible

A hero the player cannot control is only fair if you can see what he noticed. Every mirror on the winning sightline is set to reflect that entity type and all the others are cleared each turn, so the mirrors color themselves to show the path his attention actually travelled. A popup animation fires over his head naming what he locked onto, whether that was a demon, a chest or the goal.

image coming soon what he noticed

Walls and floors tile themselves

The Svelte editor auto-tiles from a 4-bit mask: each wall reads whether its up, right, down and left neighbours are walls, which picks one of 16 sprites, and a diagonal is only consulted when both cardinals beside it are walls, which is what selects the inner-corner variants without a 256-entry table. Floors come from a BFS flood fill that starts at the grid border, marks every reachable non-wall cell as outside, and fills whatever is left, so a designer draws the walls and the room floors itself. The same rules run in the game so a level looks identical in both.

image coming soon level editor

Sprites and animation as data

make_spritesheet.py packs one sheet per floor theme out of the sprites folder and writes sprite_map.json, a name to column and row lookup, so the game and the editor find a sprite by name and an artist adding a PNG never edits code. In Scala, Animation loads its frames by prefix and index from the asset directory and runs in one of three modes, Manual, Text or Cycle with a frame duration, with a hold-on-last option; the Text mode is what paces the popup lettering over the hero.

image coming soon spritesheet