Afterglow¶
an original precision platformer.
▶ Run in browserTags: 3d game platformer particles feel
Afterglow: original precision platformer (SimVX flagship demo)¶

You are the Wisp, a fading mote of light climbing to relight the Aether Spire. Dash through resonance crystals, gather glow orbs to phase through light-gates, and ride springs and moving platforms ever upward across eighteen single-screen rooms. Every death is instant and every respawn is quick: precision is the whole game. Chase the light.
Afterglow is the flagship demo for the SimVX engine and original IP. It is built
as a clean split: a deterministic, headless-testable pure-logic 2D simulation
(afterglow/sim/) presented by a lit, post-processed 3D “diorama” view
(afterglow/view/), with GPU-particle game feel, a full menu flow, and
persistent progression. The sim never imports the view or the assets, so the
game’s logic is fully unit-tested without a GPU.
Signature mechanics¶
Three ideas, each taught by level design rather than text, then braided together:
Dash through crystals (refills and chains). The air-dash is a fixed-length burst you normally get once per grounded reset. Dashing through a resonance crystal refills the dash mid-air, so a line of crystals becomes a dash-chain: cross a gap no single dash could clear by refuelling at each crystal in turn.
Glow orbs to timed glow to light-gates. Touching a glow orb lights the Wisp for a few seconds. A light-gate is solid only while the Wisp glows, so the loop is: grab the orb, race to the gate, and cross before the glow fades. Later rooms put the orb and the gate far enough apart that you must dash-chain to arrive in time.
Movement feel. Variable-height jumps, coyote time and jump buffering, wall-slide and wall-jump, springs, and moving platforms. Tight, forgiving, and the foundation every other mechanic is layered on.
Each room hides one optional shard tucked off the main path for an expert-only challenge, and tracks your best time and death count.
Controls¶
Every device feeds the same named input actions, so the simulation sees identical intent regardless of how you play.
Action |
Keyboard |
Gamepad |
|---|---|---|
Move |
Arrows / WASD |
D-pad / left stick |
Aim up-dash |
Up / W |
Up |
Jump |
Space |
A |
Dash |
Shift / J |
X |
Restart room |
R |
- |
Pause / back |
Escape |
Start |
Web and mobile touch. On a small or portrait viewport the game shows an on-screen overlay: a virtual joystick (movement and dash-aim) bottom-left, jump / dash buttons bottom-right, and a pause button top-right that opens the pause menu (and from there restart, options and quit). Touches arrive as left-clicks in the web runtime, so the virtual pad drives the exact same actions as a physical press. Everything is playable with mouse or touch alone.
How to run¶
Desktop (windowed):
# In your own copy of this directory
python main.py
# From the root of a repository checkout
uv run python examples/demos/afterglow/main.py
Web export (an HTML page plus its font-atlas PNG; serve both over http):
# In your own copy of this directory
simvx export web main.py -o afterglow.html
# From the root of a repository checkout
uv run simvx export web examples/demos/afterglow/main.py -o afterglow.html
Run the demo’s logic tests (no GPU required):
# In your own copy of this directory
pytest tests -q
# From the root of a repository checkout
uv run --package simvx-core pytest examples/demos/afterglow/tests/ -q
The three worlds¶
Eighteen rooms across three worlds, six rooms each, on a difficulty curve that hands you one new idea at a time and then asks you to combine them:
The Glade (movement). Run, variable jump, coyote/buffer over gaps, wall-slide and wall-jump, then a climb that combines all of it. No dash, crystals, orbs, or gates yet.
The Caverns (the dash and crystals). The air-dash alone, then over a gap, then resonance crystals for a single mid-air refill, then a two-crystal chain, then a constellation that demands a full dash-chain.
The Aether Spire (glow orbs and light-gates). Glow orbs and timed light-gates introduced gently, then combined with dash-chains so you must reach a gate fast and cross it before the glow fades, ending on a finale that braids every mechanic together.
Placeholder assets¶
All art and audio are generated procedurally in code under afterglow/assets/
(textures.py, sprite_gen.py, audio.py): tileable PBR-ish tile textures, the
Wisp sprite sheet, and synthesized SFX plus per-world ambient music (no
copyrighted samples, no file I/O). They are deliberate placeholders. Because the
simulation never imports the assets and the view consumes them through a single
narrow contract, you can swap any of them for real PNGs or audio files without
touching gameplay.
Source files¶
File |
Summary |
Lines |
|---|---|---|
Afterglow: an original precision platformer. |
37 |
|
Afterglow: original precision platformer (SimVX flagship demo). |
1 |
|
Generated/loaded assets for the diorama view. |
1 |
|
Procedural audio for Afterglow: synthesized SFX + per-world ambient music. |
412 |
|
Procedural Wisp sprite-sheet generator for the Afterglow diorama view. |
198 |
|
Procedural placeholder PBR textures for the Afterglow diorama view. |
192 |
|
Afterglow game root: the full state machine that hosts the flagship demo. |
831 |
|
Afterglow save / progression layer (plain JSON). |
252 |
|
Logical 2D simulation: pure Python + numpy, GPU-free, deterministic, headless-testable. |
1 |
|
Afterglow entities + the Player controller (pure Python, GPU-free). |
377 |
|
Room: ASCII parser, fixed-timestep step, swept tile collision, events. |
337 |
|
Authored room data for Afterglow: the full game, three worlds. |
795 |
|
Tile legend + flag helpers for the Afterglow logical sim. |
41 |
|
HUD, menus, and overlays built on simvx.core.ui widgets. |
1 |
|
Afterglow input layer: the one canonical cross-platform player read. |
346 |
|
Afterglow in-game HUD overlay. |
265 |
|
Afterglow menu screens. |
904 |
|
3D diorama presentation of the logical sim. Never read by the sim. |
1 |
|
GameCamera: a Camera3D that smoothly follows the Wisp and frames the room. |
184 |
|
Diorama: turn a sim Room’s static tile grid into one lit 3D mesh scene. |
266 |
|
Game-feel (juice) layer for Afterglow: particles, screenshake, hitstop, SFX. |
539 |
|
Per-world WorldEnvironment presets for the Afterglow diorama. |
165 |
|
Per-world 3D lighting rigs for the Afterglow diorama. |
202 |
|
EntityView: billboarded visuals for every dynamic sim entity, synced each frame. |
410 |
|
TitleBackdrop: a clean, intentional abstract backdrop for the title menu. |
86 |
Source¶
1"""Afterglow: an original precision platformer.
2
3# /// simvx
4# tags = ["3d", "game", "platformer", "particles", "feel"]
5# screenshot_frame = 46
6# web = { width = 960, height = 540, root = "GameRoot", responsive = true }
7# ///
8
9A complete precision platformer built on SimVX. The game logic is a deterministic
10pure-logic sim; the presentation is a lit, post-processed 3D diorama with billboard
11sprites. Textures, sprites, and audio are generated procedurally, and the game has a
12full menu flow with progression saved across three worlds.
13
14Chase the light: dash through resonance crystals, gather glow orbs to open light
15gates, and race the clock across eighteen single-screen rooms.
16
17Controls:
18 Arrows / WASD Move (Up/W aims an up-dash)
19 Space Jump
20 Shift / J Dash
21 R Restart the room
22 Escape Pause / back
23 (Gamepad and on-screen touch controls are supported.)
24"""
25
26from afterglow.game import GameRoot
27
28from simvx.graphics import App
29
30
31def main() -> None:
32 app = App(width=960, height=540, title="Afterglow")
33 app.run(GameRoot(name="GameRoot"))
34
35
36if __name__ == "__main__":
37 main()