Four builds in one post, and only the first three change anything you can see. v0.3.3 gave you a boss and swings you could read. Since then the mission stopped being a corridor.
v0.3.4— the whole map is one scene now, loaded at once, instead of rooms streamed one at a time. Criterion: plays exactly the same.v0.3.5— wall-jump and a camera that leads you. Criterion: plays better.v0.3.6— the generator lays rooms out with a 2D walk on a grid, so the map folds into vertical. The room pool was rebuilt from scratch. There’s a minimap. Criterion: plays differently.v0.3.7— a second cleanup pass, likev0.3.0. Nine phases, plays exactly the same, and the one thing you’ll notice is that the wall-slide pose now actually touches the wall.
v0.3.4–v0.3.6 were tagged but never pushed here, so this build carries all four at once.
The mission is a map now, not a line
The old mission was a chain of rooms you walked through one at a time, streamed in as you crossed a seam. The new one is one continuous map — every room standing at once on a 640×360 grid — and the generator places it with a self-avoiding walk in two dimensions: right, up, down, sometimes doubling back. So the map folds into vertical (about 8×4 cells now, against the old 17×1 straight line) and can loop back on itself.
The biggest piece of this was a measurement, not an idea: all sixteen of the old rooms were already sitting on that 640×360 grid, to the pixel — the camera bounds, the door positions, the spawn point, the floor height, all of it was a function of the grid cell. Nobody had named the grid. Naming it turned “stitch the next room onto the last one” into “read the room’s position off the grid”, and a whole class of seam-alignment bugs stopped existing.
The room pool was rebuilt from zero for this. The old rooms were corridors — one way in, one way out — and you can’t retrofit vertical travel onto a corridor. The new tiles come from one template: every tile has four sides, all sealed, and the map opens only the ones it actually connects. A hole in the floor and a hole in the wall are the same operation now. Down the middle of every tile runs a vertical column: a shaft to climb and a hole at its base, on the same axis — because a climb that ends under a solid floor isn’t a passage.
Three numbers in that column are measured, not chosen: the climb channel is 88 px wide (that’s all the climb can carry), the crossing is 64 px (bodies are 34), and the drop-hole is 64 px (a jump clears ~79, so you leap the horizontal route over the gap).
Wall-jump
A grid cell is 360 px tall. A double jump reaches about 76. Stairs sit 26 apart. A vertical link built out of ledges would be a fourteen-rung ladder — so, wall-jump, with three rules from design:
- Sliding needs you to hold toward the wall. Brushing a wall in mid-air does nothing, so the old platforming is untouched.
- Kicking off gives back your double jump — a fresh one, mid-air.
- But not twice off the same wall. One wall, one kick. A shaft is a zigzag: left wall, right wall, left wall. You need two facing walls to climb it.
The wall_contact / wall_slide / wall_jump sprite strips have been sitting unused in the project since long before this. They finally play.
A camera that looks where you’re going
The camera used to sit dead centre on the player. Now it leads your movement, it looks up or down when you ask it to, and when you’re falling fast it looks down on its own — so you see the ground before you land on it. The frame is a little wider than before (you see about 36% of a room instead of 29%).
One thing came free with this: Camera2D.offset finally has a single owner. The screen-shake was zeroing that field every frame, so anything else writing to it would have vanished without a trace. The design caught that before a line of code was written.
Minimap
A small view in the corner the whole mission, and the whole discovered map on a held Tab (stacked above the read-only relic/tattoo/souls panel that Tab already showed). The discovery rule: a room you’ve been in shows in full, a room next to one you’ve been in shows as an outline only, everything else doesn’t show at all — and a secret room never shows before you’ve walked into it.
One player for the whole mission — doors don’t heal any more
This is the change you’ll feel most. There used to be a fresh Player instance in every room host, and a component that sets your health to full when it loads — which meant every screen wipe healed you back to full. A branch, a secret, the walk up to the Legion arena. You always fought the boss on a full bar.
Now nothing swaps the scene mid-mission, so nothing re-runs that. Your health carries the whole way down. Secrets, the reliquary and the boss arena open up inside the mission scene, next to the frozen map — so you come back out the same door, the map doesn’t reset, and the dead stay dead. You go down to Legion with what you have left.
The design decision that pays for this — a guaranteed chapel before the boss door, to heal at a cost — doesn’t exist yet. For now the run is one unbroken resource curve, and whether that’s bearable without the chapel is an open question for this build.
Three rounds of playtesting and one line of code
Across v0.3.6 the map got played three times and every time the report was about geometry: “can’t reach the rooms higher up”, “walking right you fall out of the map forever”, “this level can’t be finished”. Real things got fixed along the way — a missing kill-plane in the mission scene, décor sitting in the walk path (39 px of clearance for a 34 px body), a mirrored wall-slide animation, an unresponsive wall-kick — and the pool was rebuilt.
But the cause of all three reports was one line: the spine connector was writing every edge as “right”. The rooms stood in the right places (position comes from the grid cell), but the data about the rooms lied about which way each door faced — and the seals, the portals and the minimap all trust that data. 479 of 500 seeds were unwinnable. Look in the description, not in the thing described.
v0.3.7 — the second cleanup pass
Like v0.3.0 a while back, this is a version with no gameplay changes on purpose. Same correctness bar — it plays exactly the same — and this time it’s proven: the map generator produces a byte-for-byte identical map for the same seed across 60 seeds, against the pre-cleanup code. The test suite went 31 → 33.
Nine phases, each collapsing one piece of duplication: physics-layer exclusions that four different places had each worked out; a marker convention two systems had each learned differently; three near-identical HUD bars into one; the portal, the reliquary and the NPC into one interactive-object base; two long methods broken into the steps they already were; the test scaffolding that every suite had been rebuilding for itself. Plus a pile of dead code and four doc comments that had drifted onto the wrong function.
The one visible change: the wall_contact / wall_slide frames draw the body a few pixels shy of the cell edge, and unlike the ledge-hang there was nothing correcting for it — so the wall-slide pose floated a little off the wall, on both sides. It’s pinned to the wall now.
Controls
Unchanged since v0.3.3, with wall-jump added.
| Action | Keyboard | Pad (Xbox) |
|---|---|---|
| Move | ← / → | left stick / d-pad |
| Jump (double) | Space / Enter | A |
| Wall-slide / wall-jump | hold toward the wall in the air to slide · jump to kick off | same |
| Melee (3-hit combo) | A — tap | RB |
| Charged attack | A — hold ≥ ~0.5 s | RB — hold |
| Third-hit variant | hold ↓ heavy · nothing = fast · ↑ = air launcher | same |
| Block / parry | D — hold / tap just before the hit | LT |
| Riposte | automatic — hit within 0.4 s of a parry, same enemy | same |
| Dodge (dash, i-frames) | Shift | LB |
| Shoot (8-way) | S | RT |
| Reload | R (auto on empty) | Y |
| Interact / throw-out | E | X |
| Look up / down | ↑ / ↓ held (standing still) | same |
| Full map + overview (held) | Tab | Select |
| Pause / menu | Esc | Start |
| Ledge grab | automatic; climb = jump / ↑, drop = ↓ | same |
Note: a small minimap sits in the corner the whole mission. Holding Tab opens the read-only overview — which now leads with the full discovered map, then the active relic, your tattoos and your soul count.
How to run it
| System | File | Notes |
|---|---|---|
| Windows | ultraviolet.exe (+ ultraviolet.pck beside it) | SmartScreen may warn about an unsigned file — “More info” → “Run anyway”. |
| Linux | ultraviolet.x86_64 (+ .pck beside it) | chmod +x, then ./ultraviolet.x86_64. |
| macOS | Ultraviolet.app | Unsigned: right-click → Open → confirm, or xattr -dr com.apple.quarantine Ultraviolet.app. |
Quitting: Esc in the main menu closes the game. In a run, Esc opens the pause menu — quit to the main menu from there.
Still pre-alpha — what’s not here
- Placeholder art. The player has a stand-in sprite pack; enemies, terrain and UI are coloured rectangles. Rooms are flat-shaded blocks — the grid is real, the look of it isn’t.
- Placeholder sound. Rough stand-ins, two music tracks on loop.
- Nobody has played a full mission end to end — entrance to boss — on the 2D map. Only pieces of it.
- No chapel. The run is one unbroken resource curve; the healing pocket that’s meant to sit before the boss door isn’t built.
- The map isn’t tall enough yet. Target is 12×6 cells; real maps come out about 13.6 wide by 2.5 tall. Width’s close, height needs a longer spine and more vertical tiles in the pool.
- Balance is untuned — damage, enemy HP, costs, the per-room enemy-count ramp, the wall-jump kick strength.
- No death screen, no attempt counter, no meta-progression beyond tattoos and the first soul from Legion.
How to report feedback
BUG — what happened, where (menu / hub / which part of the map / boss room), how to reproduce, which platform. If it’s a map problem, the seed helps enormously — run with --map-seed=N after -- to pin one, or just tell me what the minimap looked like.
FEEL — it works, but how does it play?
- The map — does it read as one connected place, or do you get lost? Is the minimap enough, or do you want more of it visible without holding Tab?
- Wall-jump — does a shaft feel climbable, or fiddly? Is “hold toward the wall” the right trigger, or do you keep sliding when you didn’t mean to?
- The camera — does looking down while falling help, or is it disorienting? Anywhere it whips around too hard?
- No healing at doors — is the run bearable without the chapel, or are you dead on arrival at the boss? How much health do you usually have left when you get there?
- Getting from entrance to boss — can you actually do it? Where does a run fall apart?
Leave feedback in the comments under the game or this post.
Thanks for playing something that’s still mostly rectangles.
— SolarNine · v0.3.7-pre-alpha