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
4 changes: 2 additions & 2 deletions docs/endless-runner.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,9 @@ Paths beginning with `tests/` or `scenes/` are relative to `hoppys-adventure-arc
| A3: Hazards + projectiles | Shared relief atlas, forged meshes, pit-depth and exposure guards | Maximum 11 / 5,968 per asset; 3 shared 512² maps + 256² border | `--script res://tests/assets/a3_check.gd`; `ASSET A3: PASS (158393 checks)` | `scenes/runner/hazards/dev/capture_a3.gd` | `docs/previews/assets/a3-*.png` | [A3](assets/a3.md) |
| A4: Power-ups + tools | Upward beacons, soft rings, distance-aware glyphs, bounded body emission and grab-vs-avoid affordances | 7 idle, 8 peak each / up to 2,196 peak triangles / shared relief maps and per-kind glyph textures | `--script res://tests/assets/a4_check.gd`; `ASSET A4: PASS (6035 checks)` | `scenes/runner/powerups/dev/capture_a4.gd` | `docs/previews/assets/a4-*.png` | [A4](assets/a4.md) |
| A5: Bosses + fight FX | Forged reactor, articulated Hydra, cached metal maps, pooled telegraphs/tracers/numbers | Swarm 11 / 22,080; Hydra 18 / 21,396; Monolith 14 / 6,970; FX pool 22 / 7,716; whole fight 40 draws / 4 shared 256² textures | `--script res://tests/assets/a5_check.gd`; `ASSET A5: PASS (60339 checks)` | `scenes/runner/boss/dev/capture_a5.gd` | `docs/previews/assets/a5-*.png` | [A5](assets/a5.md) |
| A6: Pursuer | Bevelled MultiMesh PR cards, Sobel normals, routed cables, threat-driven effects | 13 / 7,144 / 3 × 256² | `--script res://tests/assets/a6_check.gd`; `ASSET A6: PASS (102 checks)` | `scenes/runner/pursuer/dev/capture_a6.gd` | `docs/previews/assets/a6-*.png` | [A6](assets/a6.md) |
| A6: Pursuer | Robotic QUARANTINE hunter: two claws, receivers, lift rotors and a red light; the catch leaps past Hoppy, clamps at 1.6 s and drops a containment field | 12 / 3,840 / none | `--script res://tests/assets/a6_check.gd`; `ASSET A6: PASS (209 checks)` | `scenes/runner/pursuer/dev/capture_a6.gd` | `docs/previews/assets/a6-*.png` | [A6](assets/a6.md) |
| A7: UI | GET READY and menu grab-vs-avoid legend, first-event toasts, SPEED handoff, vector panels/icons and portrait viewport | 0 3D draws / 0 mesh tris / 0 procedural maps; 217 CanvasItems and existing 256² portrait viewport (not zero UI GPU cost) | `--script res://tests/assets/a7_check.gd`; `ASSET A7: PASS (1245 checks)`; `HUD LEGIBILITY: PASS (60 labels checked)` in visual smoke | `scenes/runner/ui/dev/capture_a7.gd` | `docs/previews/assets/a7-*.png` | [A7](assets/a7.md) |
| A8: Audio | Deterministic layered PCM, FM transients, filtered noise, family envelopes, leased reverb/compressor/delay buses | 0 / 0 / 0; 32 recipes, 3,901,938 checked PCM bytes, peak 0.789972 | `--script res://tests/assets/a8_check.gd`; `ASSET A8: PASS (2323 checks)` | `scenes/runner/audio/dev/capture_a8.gd` | `docs/previews/assets/a8-*.png` | [A8](assets/a8.md) |
| A8: Audio | Deterministic layered PCM, FM transients, filtered noise, family envelopes, leased reverb/compressor/delay buses | 0 / 0 / 0; 32 recipes, 3,901,938 checked PCM bytes, peak 0.789972 | `--script res://tests/assets/a8_check.gd`; `ASSET A8: PASS (2333 checks)` | `scenes/runner/audio/dev/capture_a8.gd` | `docs/previews/assets/a8-*.png` | [A8](assets/a8.md) |
| A9: Post-processing | Single screen-reading shader: grading, grain, vignette, hit aberration, letterbox, speed streaks, Nitro lift | 1 fullscreen pass / 2 / 0 generated textures; implicit screen backbuffer copy is additional storage/bandwidth | `--script res://tests/assets/a9_check.gd`; `ASSET A9: PASS (147 checks)` | `scenes/runner/ui/dev/capture_a9.gd` | `docs/previews/assets/a9-*.png` | [A9](assets/a9.md) |

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.
Expand Down
20 changes: 16 additions & 4 deletions hoppys-adventure-arcade/tests/assets/a6_check.gd
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,13 @@ func check(ok: bool, message: String) -> void:
failures += 1
push_error(message)
func _initialize() -> void: call_deferred("run")
## The hunter rig's bounds. The quarantine field is a separate world-space effect dropped around
## Hoppy during a catch, so it is not part of the hunter's envelope.
func bounds(node: Node3D) -> AABB:
var result := AABB()
var first := true
for mesh: MeshInstance3D in node.find_children("*","MeshInstance3D",true,false):
if mesh == node.get("_field"): continue
var box: AABB = node.global_transform.affine_inverse()*mesh.global_transform*mesh.mesh.get_aabb()
result = box if first else result.merge(box)
first = false
Expand Down Expand Up @@ -46,13 +49,22 @@ func run() -> void:
visual._process(0.1)
check(not visual._fans[0].rotation.is_equal_approx(rotor),"Visible propulsion rotates")
var count := visual.find_children("*","",true,false).size()
var start_z: float = visual._wall.global_position.z
visual.play_catch()
visual._process(0.4)
check(absf(visual._arms[0].rotation.x) > 0.3,"Capture deploys claws")
visual._process(visual.CLAMP_AT)
check(absf(visual._arms[0].rotation.x) > 0.3,"Capture clamps the claws at CLAMP_AT")
check(visual._field.visible,"Quarantine field drops once the claws shut")
visual.play_catch()
check(is_equal_approx(visual._reaction_time,0.4),"Catch idempotent")
check(is_equal_approx(visual._reaction_time,visual.CLAMP_AT),"Catch idempotent")
visual._process(1.0)
check(visual._wall.scale.is_equal_approx(Vector3.ONE) and visual._wall.position.z > 2,"Catch lunges without giant growth")
var held: Transform3D = visual._wall.global_transform
var unscaled := held.basis.get_scale().is_equal_approx(Vector3.ONE)
check(unscaled and held.origin.z < start_z - 4.0,"Catch leaps past Hoppy without giant growth")
visual.set_threat(1)
check(visual._reaction == &"catch","Catch holds while the threat stays at 1")
visual.set_threat(0)
check(visual._reaction == &"idle" and not visual._field.visible,
"Run reset ends the catch and lifts the field")
visual.set_threat(1)
var pose: Transform3D = visual._wall.transform
visual.set_threat(0)
Expand Down
8 changes: 6 additions & 2 deletions hoppys-adventure-arcade/tests/assets/a8_check.gd
Original file line number Diff line number Diff line change
Expand Up @@ -170,8 +170,11 @@ func run() -> void:
audio.play_ui_click()
var heard := {}
audio.sound_played.connect(func(kind: StringName, _stream: AudioStream) -> void: heard[kind] = true)
# Existing mock timeline exercises all 32 signal-triggered recipes.
for i in 405:
# The mock timeline exercises all 32 signal-triggered recipes. Run it until it finishes, so the
# Game Over sting still fires when config.caught_sequence_seconds changes (#61 made it 3.0 s).
var ticks := 0
while mock.state != &"finished" and ticks < 600:
ticks += 1
audio.one_shots.stop()
audio.one_shots.play()
audio._playback = audio.one_shots.get_stream_playback()
Expand All @@ -180,6 +183,7 @@ func run() -> void:
mock.advance_demo(0.1)
audio._process(0.1)
check(audio.active_voice_count() <= 10, "voice cap")
check(mock.state == &"finished", "demo timeline reaches Game Over (%d ticks)" % ticks)
for kind: StringName in Synth.RECIPES: check(heard.has(kind), "trigger exercised: " + kind)
audio._stop_all()
audio.one_shots.play()
Expand Down
Loading