Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions ASSETS_LICENSES.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ These assets were made for this project, either by hand, by procedure, or with i
| Bay Area Blitz music | `Audio/Platformer/Bay Area Blitz/` | Music by Erik Thorelli, made with Suno v6 for this game. Erik holds the rights and grants their use in the game and in this repository. Prompts, Suno song IDs, loop points and delivery steps in `PROMPTS.md`. | ✅ |
| Orbital Ops music | `Audio/Platformer/Obital Ops/` | Music by Erik Thorelli, made with Suno v6 for this game. Erik holds the rights and grants their use in the game and in this repository. Prompts, Suno song IDs, loop points and delivery steps in `PROMPTS.md`. | ✅ |
| Hoppy 3D mascot | `runner/hoppy/` | Built by `tools/blender/build_hoppy.py` | ⚠️ brand sign-off |
| CodeRabbit hero rabbit (runner model) | `runner/hoppy_hero/` | Artist handover mesh and textures (`source/`), skinned and retargeted by `tools/blender/build_hoppy_hero.py` | ⚠️ brand sign-off |
| Platformer stage-clear stinger | `Audio/Platformer/stinger_stage_clear.ogg` | Music by Erik Thorelli, made with Suno v6 for this game. Erik holds the rights and grants their use in the game and in this repository. Prompt, Suno song ID and edit in `Audio/Platformer/PROMPTS.md`. | ✅ |
| Runner props, previews and procedural assets | `runner/` | See [`runner/LICENSES.md`](hoppys-adventure-arcade/Assets/runner/LICENSES.md) | ✅ |
| Bay Area Blitz pack | `bay-area-blitz-assets-only/` | Image generation | ⚠️ confirm the generator's terms allow redistribution |
Expand Down
4 changes: 2 additions & 2 deletions docs/endless-runner-contract.md
Original file line number Diff line number Diff line change
Expand Up @@ -829,8 +829,8 @@ the beats and the skip; the frontend draws the title card and countdown from tha
HUD clock reads 00:00 and the score 0 at GO.
- **Beats.** `run_intro_beat(index, label)` goes out as the intro's clock reaches each time in
`run_intro_*_beat_times` (full `title` 1.0, `3` 3.0, `2` 3.8, `1` 4.6, `GO!` 5.4; short `READY` 1.0, `GO!` 1.6),
always in index order. The `title` beat is the title card's cue and plays Hoppy's `victory` clip through
`runner_player.gd` → `visual.celebrate()`.
always in index order. The `title` beat is the title card's cue. Hoppy does not react to it: the `victory` clip
it used to play (through `runner_player.gd` → `visual.celebrate()`) was removed from the intro.
- **Hold.** From `run_intro` until the **last beat (GO)** the StageManager holds `cinematic_hold`: manual controls
are off (autopilot included, through `refresh_player_controls()`) and the corridor eases to
`boss_cinematic_speed_scale`. GO hands both back before it is sent. The camera and the mirrors keep following
Expand Down
13 changes: 10 additions & 3 deletions docs/endless-runner.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,14 +85,21 @@ Paths beginning with `tests/` or `scenes/` are relative to `hoppys-adventure-arc

A4 peak census includes the collection burst; code_review has the highest triangle count. A5 whole-fight draws are a concurrent budget, not the sum of every boss. A9's current 147-check verification supersedes both the earlier 126- and 134-check transcripts.

**Hoppy hero look (recipe 11, joint 17).** The runner Hoppy is the Heroes vs. Villains armored hero as a cyberpunk action figure, following the beat 'em up sprites (`Assets/heroes-vs-villains-assets-only/frames/hoppy/`) and the hero intro art (`Assets/beatemup-story/heroes/send_in_the_rabbit.png`): a small rabbit head with a cream muzzle and almond eyes, long upright ears (tips at the 1.8 m standing height), a tall V-shaped torso and long limbs (ankle 0.10, knee 0.44, hip 0.80, shoulder 1.15, skull centre 1.335 m). The graphite muscle suit has squared, plated sections with sculpted pecs, abs and shoulder blades plus baked panel lines; graphite armour pauldrons and a chest plate carry the orange rabbit emblem; orange finned gauntlets, fisted gloves and orange boots with a pointed cuff; a brown utility belt with a gold buckle and pouches; and a graphite cape lined in orange with a stand-up collar, deep folds and a five-point jagged hem. Emblems, the chest plate and the LED pads are chamfered meshes from marching-squares contours, wrapped onto the torso, plate or cape by ray casts along smooth normals. The cape hangs on two extra bones (`cape`, `cape_tip`, 33 bones in all) that flare with the run, billow in the fall and tuck flat in the slide (Godot-skinned top 0.549 m). The four-segment power-up LED strip sits on the back of the cape, under its rabbit badge. Recipe 11 makes him read badass rather than cute: fierce up-swept almond eyes with glowing amber slit-pupil irises and a heavy black lid, low stern brows, a smirk, an angular cyan HUD visor over the right eye with a temple arm and LED, metal rings on the left ear, and emissive cyan circuit trim on the chest plate, pauldrons, gauntlets, boots and the cape hem. The run is an athletic sprint: forward lean that breathes with each footfall, hip and shoulder counter-twist with a stabilised head, a bigger stride and a hard arm pump carried slightly forward, ears streaming back, and a livelier cape. Gait one-shots layer their torso overlays on top of the run values, so each still ends on its run exit pose. The runtime face idles and runs focused with a confident half-smile. There are no transparent surfaces. The face rig's brow and mouth travel is scaled by `FACE_SCALE` (0.55) for the smaller face; the jump-tuck guard's hip-to-heel limit is 1.3 thigh lengths. The cape covers the cream tail from behind, so the A1 capture's rear chase views gate only the orange class; cream fur stays gated in the front views and the corridor face check.
**CodeRabbit hero rabbit (what the runner shows).** The runner draws the artist's low-poly CodeRabbit hero rabbit (white, orange and black armour, chest emblem, orange cape), `Assets/runner/hoppy_hero/hoppy_hero.glb`. The handover shipped a neutral-pose OBJ and TGA textures; its Maya rig cannot be exported here, so `tools/blender/build_hoppy_hero.py` scales the mesh to the same 1.8 m ear-tip height and -Z facing, builds the procedural Hoppy's 33-bone skeleton (same names and rolls) on the rabbit's own joints, skins each mesh part with bone-heat weights limited to the bones it may follow, and retargets all thirteen clips from `Assets/runner/hoppy/hoppy.glb`: each bone's local rotation is re-expressed in the new rest frame, root and hips travel scale with the shorter legs, the root lifts wherever a pose would dip under the deck, raised arms swing out until the paws clear the big head (victory, power-up), and the splayed ears take 45% of Hoppy's ear motion. Eyeballs ride the eye bones, so the face rig still blinks and squints; the brows and mouth corners carry no geometry. A four-segment LED band across the cape above its hem keeps the power-up meter (invisible until lit). Rebuild with `prep_hoppy_hero_textures.py` (TGA to 1024 px PNG, mixmap G to ORM roughness), then the Blender script, then re-import and re-bake the roll. The procedural model below remains the rig and clip source.

**Cape and ear physics.** `scenes/runner/player/hifi/sway_rig.gd` is a `SkeletonModifier3D` that runs last, over the clips and the other modifiers. Each link (`cape`, `cape_tip`, `ear_*`, `ear_tip_*`) owns a point mass at its bone tail, simulated in world space and pulled by a spring toward where the clip puts the tail, so lane changes, jumps, landings and the clip's own motion make it lag, overshoot and settle. The cape is heavy and loose (about 1.2 Hz, under-damped, so it swings behind the stride and back past rest after a dash); the ears are light and stiff (about 10 Hz, so they ride the stride and whip only on dashes and jumps). `hoppy_runner_visual.gd` feeds it the frame time, a running-air wind (steady plus gusts, scaled by run speed: the cape streams back and flutters) and a 0.35 swing scale during the slide. Each link has a swing limit, and the cape may not swing forward into the body. A gap over 0.25 s, a clip pose that jumps, or `settle()` snaps the masses back to the clip pose; posed fixtures (`capture_a1.gd` `pose_for_view`) settle, so stills and the asset checks see the clip pose. The cape and ear skin weights are hand-tuned gradients in `build_hoppy_hero.py` (collar to chest, cloth curving over the `cape`/`cape_tip` joint, ears blending from the skull through `ear` to `ear_tip`). Checks: `tests/runner_sway_check.gd`; contact strips: `Godot --path hoppys-adventure-arcade --always-on-top --script res://scenes/runner/player/dev/capture_sway.gd -- --output=<folder>`.

**Hoppy hero look (recipe 11, joint 17).** The procedural Hoppy (the clip source) is the Heroes vs. Villains armored hero as a cyberpunk action figure, following the beat 'em up sprites (`Assets/heroes-vs-villains-assets-only/frames/hoppy/`) and the hero intro art (`Assets/beatemup-story/heroes/send_in_the_rabbit.png`): a small rabbit head with a cream muzzle and almond eyes, long upright ears (tips at the 1.8 m standing height), a tall V-shaped torso and long limbs (ankle 0.10, knee 0.44, hip 0.80, shoulder 1.15, skull centre 1.335 m). The graphite muscle suit has squared, plated sections with sculpted pecs, abs and shoulder blades plus baked panel lines; graphite armour pauldrons and a chest plate carry the orange rabbit emblem; orange finned gauntlets, fisted gloves and orange boots with a pointed cuff; a brown utility belt with a gold buckle and pouches; and a graphite cape lined in orange with a stand-up collar, deep folds and a five-point jagged hem. Emblems, the chest plate and the LED pads are chamfered meshes from marching-squares contours, wrapped onto the torso, plate or cape by ray casts along smooth normals. The cape hangs on two extra bones (`cape`, `cape_tip`, 33 bones in all) that flare with the run, billow in the fall and tuck flat in the slide (Godot-skinned top 0.549 m). The four-segment power-up LED strip sits on the back of the cape, under its rabbit badge. Recipe 11 makes him read badass rather than cute: fierce up-swept almond eyes with glowing amber slit-pupil irises and a heavy black lid, low stern brows, a smirk, an angular cyan HUD visor over the right eye with a temple arm and LED, metal rings on the left ear, and emissive cyan circuit trim on the chest plate, pauldrons, gauntlets, boots and the cape hem. The run is an athletic sprint: forward lean that breathes with each footfall, hip and shoulder counter-twist with a stabilised head, a bigger stride and a hard arm pump carried slightly forward, ears streaming back, and a livelier cape. Gait one-shots layer their torso overlays on top of the run values, so each still ends on its run exit pose. The runtime face idles and runs focused with a confident half-smile. There are no transparent surfaces. The face rig's brow and mouth travel is scaled by `FACE_SCALE` (0.55) for the smaller face; the jump-tuck guard's hip-to-heel limit is 1.3 thigh lengths. The cape covers the cream tail from behind, so the A1 capture's rear chase views gate only the orange class; cream fur stays gated in the front views and the corridor face check.

**Blender pipeline.** Authoring and turntable rendering are host-only because Blender crashes in the sandbox. From `hoppys-adventure-arcade/`, run the rebuild wrapper (which applies the shared atlas layout), render turntables, then import the GLB and baked textures into Godot. Runtime animation is driven by `scenes/runner/player/hoppy_runner_visual.gd`; Blender is not a runtime dependency. See [A1](assets/a1.md) for provenance and bake details. These commands are documentation only in this cleanup; Blender and graphical scenes were not run.

```sh
/Applications/Blender.app/Contents/MacOS/Blender --background --python-exit-code 1 --python tools/blender/rebuild_hoppy.py -- --out Assets/runner/hoppy/hoppy.glb
/Applications/Blender.app/Contents/MacOS/Blender --background --python-exit-code 1 --python tools/blender/render_hoppy.py -- Assets/runner/hoppy/hoppy.glb /tmp/hoppy-turntables
uv run --python 3.12 --no-project --with pillow python tools/blender/prep_hoppy_hero_textures.py <handover>/Textures
/Applications/Blender.app/Contents/MacOS/Blender --background --factory-startup --python-exit-code 1 --python tools/blender/build_hoppy_hero.py -- --preview /tmp/hoppy-hero-previews
/Applications/Godot.app/Contents/MacOS/Godot --headless --log-file /tmp/a1-import.log --path . --import
/Applications/Godot.app/Contents/MacOS/Godot --headless --path . --script res://scenes/runner/player/dev/bake_hoppy_roll.gd
```

**Grab-vs-avoid affordance rule.** Hazards use DANGER, warning stripes and downward/ground threats. Pickups use mint/orange, upward beacons and soft rings, never DANGER or warning stripes. Power-ups use MINT; tools retain MATRIX sculpture cores with ORANGE frames, beams, rings and glyphs. The A7 legend teaches a mint shield for power-ups, an orange wrench for tools and a striped DANGER triangle for hazards. First-event toasts reinforce collection and unblocked-damage meanings. See [A4](assets/a4.md) and [A7](assets/a7.md).
Expand Down Expand Up @@ -252,7 +259,7 @@ The navy environment and dim MATRIX grid/rain reuse the hub preview palette and

| Visual | Source | Licence | Replace-by |
| --- | --- | --- | --- |
| Hoppy model, animations, and effects | `Assets/runner/hoppy/hoppy.glb`, authored by `tools/blender/build_hoppy.py` (rebuild with `tools/blender/rebuild_hoppy.py`) and instanced under `Root/Model` by `scenes/runner/player/hoppy_runner_visual.tscn`; effects live in `hoppy_runner_visual.gd`. To swap the model, replace the GLB under `Root/Model`, retain the feet origin, -Z facing and 1.8 m height, keep the thirteen action names, and preserve the scene root, six hooks and effects. Re-bake `hifi/hoppy_roll.tres` (or set `use_baked_roll = false`), since the baked roll overrides the GLB's. Re-run the smoke bounds checks and host preview, including the 0.9 m roll (slide). | Original project source | Rigged glTF via the model-swap procedure below. |
| Hoppy model, animations, and effects | `Assets/runner/hoppy_hero/hoppy_hero.glb` (the CodeRabbit hero rabbit, built by `tools/blender/build_hoppy_hero.py` with the clips of `Assets/runner/hoppy/hoppy.glb`, which `tools/blender/build_hoppy.py` authors; rebuild that with `tools/blender/rebuild_hoppy.py`), instanced under `Root/Model` by `scenes/runner/player/hoppy_runner_visual.tscn`; effects live in `hoppy_runner_visual.gd`. To swap the model, replace the GLB under `Root/Model`, retain the feet origin, -Z facing and 1.8 m height, keep the thirteen action names, and preserve the scene root, six hooks and effects. Re-bake `hifi/hoppy_roll.tres` (or set `use_baked_roll = false`), since the baked roll overrides the GLB's. Re-run the smoke bounds checks and host preview, including the 0.9 m roll (slide). | Original project source | Rigged glTF via the model-swap procedure below. |
| pr_backlog_low | `scenes/runner/hazards/visuals/pr_backlog_low_visual.gd` + shared `hazard_art.gd`: Three rows of navy PR cards, orange/red strips, wobble, hit scatter/fade and mint shrink; AUTO-FIXED. | Original project source | Replace artwork within the existing visual root; retain contract hooks, bounds and pause behavior. |
| pr_backlog_high | `scenes/runner/hazards/visuals/pr_backlog_high_visual.gd` + shared `hazard_art.gd`: Rail and hanging stale/CI cards, sway, hit drop/bounce, mint shrink; exact red footprint plus inset green safe-gap quad. | Original project source | Replace artwork within the existing visual root; retain contract hooks, bounds and pause behavior. |
| bug_swarm | `scenes/runner/hazards/visuals/bug_swarm_visual.gd` + shared `hazard_art.gd`: Red core, six legs, 36 atlas glyph particles, leg jitter and core pop; throw new Error(). | Original project source | Replace artwork within the existing visual root; retain contract hooks, bounds and pause behavior. |
Expand Down Expand Up @@ -1073,7 +1080,7 @@ Backend hand-off (contract §11.15 is authoritative):
until a skip. The skip window closes at GO, so a jump pressed on GO is a jump. The HUD hides its widgets and GET READY for the intro and opens GET READY with the run.
- **Camera.** `camera_rig.set_run_intro(progress, mode, focus)` places the lens off Hoppy's feet from the frontend
`SHOTS` table (fallback shots built in). The rest pose is `[8.0, 4.0, 0.0, 60.0, 2.5]`.
- **Hoppy.** The `title` beat plays Hoppy's `victory` clip through the player visual's `celebrate()`.
- **Hoppy.** Hoppy keeps his normal pose through the intro. The `title` beat no longer plays his `victory` clip (the raised-arms cheer); that clip is kept for stage clears and boss defeats.
- **Audio.** `intro_whoosh` under the full intro's fly-through, `intro_title` on the title beat, `intro_count` on
each count (and READY), `intro_go` on GO; the music is ducked 12 dB until GO.
- **Capture.** `Godot --path hoppys-adventure-arcade --always-on-top --script
Expand Down
1 change: 1 addition & 0 deletions hoppys-adventure-arcade/Assets/runner/LICENSES.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ No external downloads. F5 reuses the existing bundled music package.
| Procedural runner SFX | scenes/runner/audio/sfx_synth.gd | Project contributors | Original deterministic PCM recipes | Project source terms; no third-party asset licence | Original |
| Cyberpunk Street BGM | res://Assets/cyberpunk-street-files/Assets/music/cyberpunk-street.ogg | Luis Zuno / ansimuz | Assets/cyberpunk-street-files/public-license.pdf | CC0 | none; the PDF does not name the music's composer |
| Blender Hoppy mascot | Assets/runner/hoppy/** | Project contributors | generated in-repo by tools/blender/build_hoppy.py (Blender 5.2.2) | Project licence | Original work |
| CodeRabbit hero rabbit | Assets/runner/hoppy_hero/** | CodeRabbit artist handover | OBJ and textures in source/, built by tools/blender/build_hoppy_hero.py (Blender 5.2.2) | Project licence | Original work, brand sign-off |
| Hydra conflict-marker glyphs | Assets/runner/bosses/merge_conflict_hydra/** | DejaVu fonts contributors / Bitstream | Blender bundled DATAFILES/fonts/DejaVuSansMono.woff2 | [Bitstream Vera and DejaVu Fonts License](https://dejavu-fonts.github.io/License.html); font name and SHA-256 recorded in build.json | Converted <<<<<<<, ======= and >>>>>>> outlines to mesh and baked atlas; no font file redistributed |
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
{
"generator": "tools/blender/build_hoppy_hero.py",
"script_sha256": "3e69655f2529155e14ca39e3d248b640c6c8a0276b122de6589c81241e9983cd",
"blender": "5.2.2 LTS",
"source_mesh": "rabbit_mesh.obj",
"clip_source": "Assets/runner/hoppy/hoppy.glb",
"height_m": 1.8,
"cm_to_m": 0.022799,
"travel_scale": 0.7125,
"triangles": 12126,
"triangle_cap": 48000,
"animations": [
"dead",
"fall",
"hurt",
"idle",
"jump",
"land",
"lane_dash_left",
"lane_dash_right",
"powerup_react",
"roll",
"run",
"shield_brace",
"victory"
],
"clip_seconds": {
"dead": 1.2,
"fall": 0.8,
"hurt": 0.6,
"idle": 1.6,
"jump": 0.5,
"land": 0.2,
"lane_dash_left": 0.2667,
"lane_dash_right": 0.2667,
"powerup_react": 0.5,
"roll": 0.8,
"run": 0.6,
"shield_brace": 0.4,
"victory": 1.2
},
"clip_bounds_z": {
"dead": [
-0.0,
1.8798
],
"fall": [
0.0,
1.8456
],
"hurt": [
-0.0,
1.8808
],
"idle": [
0.0017,
1.8104
],
"jump": [
0.0679,
1.8822
],
"land": [
-0.0,
1.6852
],
"lane_dash_left": [
-0.0,
1.7973
],
"lane_dash_right": [
-0.0,
1.7973
],
"powerup_react": [
-0.0,
1.805
],
"roll": [
-0.0,
0.7358
],
"run": [
-0.0,
1.8339
],
"shield_brace": [
-0.0,
1.7634
],
"victory": [
-0.0,
1.7239
]
},
"ground_lift_m": {
"dead": 0.1618,
"fall": 0.0495,
"hurt": 0.0852,
"idle": 0.0,
"jump": 0.0,
"land": 0.0146,
"lane_dash_left": 0.0276,
"lane_dash_right": 0.0276,
"powerup_react": 0.0183,
"roll": 0.1341,
"run": 0.0183,
"shield_brace": 0.0242,
"victory": 0.0183
},
"arm_swing_deg": {
"land": 2.5,
"lane_dash_left": 5.0,
"lane_dash_right": 5.0,
"powerup_react": 45.0,
"roll": 5.0,
"run": 2.5,
"shield_brace": 2.5,
"victory": 62.5
},
"ear_damp": 0.45,
"materials": [
"hero body",
"hero eyes",
"hero head",
"hero cape"
],
"led_band": [
0.16,
0.3
],
"led_segments": 4
}
Binary file not shown.
Loading
Loading