feat: initial implementation v0.1.0 — single player puppet + WASD + map

Composer module: single-player character as puppet (humanoid 4-bone
rig: torso, head, leg_l, leg_r) at world (320, 240) on a 20x20
v0.1-format tilemap.

- WASD direct movement, normalized for diagonals, 120 px/s.
- Camera-chase via lib-core.camera target-provider (camera follows
  puppet position frame-to-frame).
- Idle and walk keyframe animations: idle is a 2s torso-sway on the
  upper track; walk is a 0.6s leg-cycle on the lower track.
- Animation-state transitions driven by movement input: walk while
  WASD-active, idle when released.
- Headtrack: head bone (marked look_at: true in rig) rotates each
  frame to face the mouse cursor's world position via
  puppet.set_look_target.
- ESC -> launcher.

CI hooks (env-var-gated, no-op in normal play):
- SPOREL_CI=1: emits 'vagrant: frame_avg_ms=N' after 60 frames and
  'vagrant: render_frame_ok' per frame from the render hook, then
  engine.exit(0). Smoke stages consume these markers.
This commit is contained in:
Axel Meyer
2026-05-17 20:21:31 +02:00
commit 2817613490
10 changed files with 293 additions and 0 deletions

13
rigs/humanoid.rig.json Normal file
View File

@@ -0,0 +1,13 @@
{
"id": "humanoid",
"bones": [
{ "id": "torso", "parent": null, "rest": { "x": 0, "y": 0, "angle": 0 }, "color": [180, 140, 100] },
{ "id": "head", "parent": "torso", "rest": { "x": 0, "y": -16, "angle": 0 }, "look_at": true, "color": [220, 180, 140] },
{ "id": "leg_l", "parent": "torso", "rest": { "x": -4, "y": 8, "angle": 0 }, "color": [80, 60, 40] },
{ "id": "leg_r", "parent": "torso", "rest": { "x": 4, "y": 8, "angle": 0 }, "color": [80, 60, 40] }
],
"tracks": [
{ "id": "lower", "bones": ["leg_l", "leg_r"] },
{ "id": "upper", "bones": ["torso", "head"] }
]
}