Commit Graph

17 Commits

Author SHA1 Message Date
Axel Meyer
77f3e726ae fix(vagrant): hip-anchors body-relative; leg-orientation procedural
User feedback: 'anchorpoints sind hüftgelenke und können sich nicht
frei drehen. hüfte bleibt zum körper statisch'.

Architecture:
- legs.parent = body (was lower_control). Hip position cascades from
  body.world.rot, so hips stay at body-frame left/right regardless of
  body rotation. lower_control virtual bone removed (no longer needed).
- Procedural 'leg_orientation' sets leg.local.rot = walk_dir - body.rot
  each frame, so leg.world.rot = walk_dir (independent of body cascade).
  Requires puppet v0.4.2 per-channel write_bone (walk_anim writes leg.scl
  while procedural writes leg.rot — disjoint channels).

Result: legs visually attach at body's anatomical left/right hips no
matter where body faces; stride oscillation aligns with WASD walk
direction. Hip position no longer drifts with walk direction.
2026-05-18 21:57:20 +02:00
Axel Meyer
0a7ef7f270 fix(vagrant): legs rotate to walk direction (user preference)
User feedback: 'Beine sollten in die richtung oszillieren, in die
gegangen wird, nicht nach norden/süden relativ zum fenster.'

Old: lower_control.rot = wedge_deg (substrate's body-relative ±30°
sub-angle), legs always oscillated near world-up axis.

New: lower_control.rot = atan(move_x, -move_y) = walk direction in
sprite-top-up convention. Legs visually rotate to align with WASD
direction → stride animation cycles along the walk axis.

Side-effect: 4-direction-anim picker collapsed to single
walk_fwd_lower (the rotation handles directional differentiation;
4 anims kept on disk for later gait-style work). Bumps puppet dep
to 0.4.1 (head south-flick fix).
2026-05-18 21:48:10 +02:00
Axel Meyer
3f176f6105 fix(vagrant): remove head sprite_rot + invert signed-angle cross-sign
Two fixes from manual interactive verification after iteration-3:

1. Head 90° CCW off → removed sprite_rot=-90 from head bone. The
   v0.3.3 sprite_rot fix was based on misobservation: at that point
   the persistent-state-rate-limit bug was active and head was
   wiggling within ±10° of an arbitrary initial direction, perceived
   as 90° CW off. With v0.3.2+ persistent-state fix and v0.4.0 slerp,
   head rotates correctly when sprite-natural-face is -Y (matching
   body-sprite convention).

2. Legs walked in inverted sector → signed_angle_2d cross-component
   was using Y-up math convention but Sporel screen-coords are Y-down.
   With Y-down, what's CCW in math is CW visually. Flipping the cross
   sign aligns sector selection: body up + player walks right → CW
   visually → walk_right_lower (was wrongly returning walk_left).

Front/back leg-anchor issue (#3 from user report) deferred — likely an
optical-overlap artifact from rotated body sprite + world-frame leg
positions, will reassess after #1+#2 fixes are visually verified.
2026-05-18 21:38:43 +02:00
Axel Meyer
e6e4e3805b fix(vagrant): bump version 0.3.0→0.4.0 + puppet dep 0.3.3→0.4.0
Iteration-3 implemented Subterrain control model but forgot to bump
the consumer manifest. Engine lib-resolver does exact strcmp so
'0.3.3' fails against published 0.4.0 → ENGINE_ERR_LIB_DEP_MISSING
FATAL at module load.

Recurring pattern (cf. feedback_sporel_dep_versions memory) — every
lib-bump must update all consumer manifests in the same commit-set.
2026-05-18 21:24:11 +02:00
Axel Meyer
794287fd10 feat(vagrant-skeleton): Subterrain-style lower-body control model
Add lower_control virtual bone (reparents legs for independent orientation).
Update look_at fields: body uses "soft" target with slerp=6, head uses
"aim" target with instant snap and ±60° clamp. Rename walk.anim.json to
walk_fwd_lower.anim.json and add walk_back_lower, walk_left_lower,
walk_right_lower anims ported from substrate. Port HandleAnimationLower:
signed-angle sector selection (±45°/±135°) drives 4-directional walk anim
choice; wedge clamp sets lower_control rotation. Separate aim/soft look
targets both track raw mouse for now.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 21:19:08 +02:00
Axel Meyer
926cb9da29 fix(vagrant): head sprite_rot=-90 corrects 90° CW visual offset
head_001.png is drawn with face pointing +X (right) at rot=0, but the
look-at math assumes sprite-top (-Y) is forward. Without compensation,
head visually appears 90° clockwise off when math says 'point at mouse'.

sprite_rot=-90 on head bone aligns sprite-top with bone-forward at
render time. Body, shoulder, and arm sprites already match the
sprite-top=forward convention so no sprite_rot needed there.

Also bumps puppet dep to 0.3.3 and removes the temporary debug print.
2026-05-18 20:42:13 +02:00
Axel Meyer
60afa48976 fix(vagrant): wrap world rendering in camera.begin/finish
Map + furniture + puppet now render via the 2D camera so the camera
target (= puppet position) appears at screen-center. Without the wrap,
world rendering happened in raw window-coords: puppet at world (320,240)
appeared at screen upper-left, mouse-screen-to-world math was correct
but mouse cursor over the visible puppet computed dx/dy from puppet's
world position to mouse_world which was OFF-by-(w/2,h/2). Visual result:
head pointed in wrong direction relative to actual mouse position.

Spine-prototype already used this pattern (init.lua:128). Aligning
vagrant-skeleton with that convention.
2026-05-18 20:26:45 +02:00
Axel Meyer
c3f2730119 fix(vagrant): bump puppet dep 0.3.1 -> 0.3.2 to match staged lib
Iteration 2 bumped lib-core.puppet to v0.3.2 (persistent look_at_state
fix) but the vagrant-skeleton manifest dep was not updated. Engine
lib-resolver does exact strcmp → module fails to load with
ENGINE_ERR_LIB_DEP_MISSING at launcher select.
2026-05-18 20:18:48 +02:00
Axel Meyer
9de4924706 exp(vagrant): try procedural lower-body, drop WASD-to-root coupling
- humanoid.rig.json: removed locomotion-block (apply_locomotion no-ops
  now). head: removed look_at_speed (instant snap). body: unchanged
  (look_at_speed=180 lazy).
- init.lua: removed set_procedural("facing", ...) — root stays at
  rest.rot=0. walk.anim + idle_lower.anim no longer loaded/played
  (files retained on disk for revert). New set_procedural("walk_cycle",
  ...) drives legs per-frame: walk_phase advances at 1.25Hz, sin-cycle
  on leg.scl, walk_dir applied to leg.rot. Idle: legs scl=0.
- Lazy body + instant head + head-leading: head responds immediately
  to mouse, body lags via look_at_speed=180.

This is an experiment. If procedural feels worse, revert by re-enabling
walk.anim + idle_lower.anim + locomotion-block.
2026-05-18 20:13:44 +02:00
Axel Meyer
03a536984d fix(vagrant): iteration — body+head look-at, WASD-driven leg-facing, idle-collapse
- humanoid.rig.json: root removed from upper track; body look_at + slow speed
  (180 deg/s, lazy); head fast speed (480 deg/s) + +-90 deg limits; puppet
  dep bumped to 0.3.1
- animations/idle_lower.anim.json (NEW): leg+foot scl=[mirror, 0] keeps legs
  invisible at idle (locomotion skips animated bones; foot cascade zeros out)
- init.lua: set_procedural 'facing' callback writes root.rot from
  last_walk_rot_deg each frame; WASD-vector updates last_walk_rot_deg
  via atan(dx, -dy); idle_lower played parallel to idle, stopped during walk

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 19:51:56 +02:00
Axel Meyer
00d10bbd47 fix(vagrant): manifest dep versions match resolver expectations
Engine lib-resolver does exact strcmp (not semver-range), so '^0.3.0'
fails to match published 0.3.0. Also pin lib-asset.prototype-subterrain
to 0.1.1 (the published patch version).

Surfaced during Phase-4 install-reference verify after vagrant-skeleton
v0.3.0 cutover.
2026-05-18 18:57:11 +02:00
Axel Meyer
fa511204c2 feat(vagrant): v0.3.0 — substrate-port rig + animations + locomotion
- humanoid.rig.json rewrite: legs->root, rest.rot+rest.scl on all bones,
  Y-mirror via scl=-1 on leg_l/r/foot_l/r, locomotion-block with
  procedural footplant config
- walk.anim.json: substrate walk_fwd_lower port; track=lower; pos+scl
  channels on legs+feet
- walk_upper.anim.json (NEW): substrate walk_upper port; arm-swing
- idle.anim.json: substrate idle_upper port; pos+rot on shoulders+arms
- init.lua: walk_upper parallel-play wiring
- manifest bump v0.2->v0.3; puppet dep ^0.3.0
2026-05-18 18:55:34 +02:00
Axel Meyer
3457a7eab8 feat: sprite-mode test-chamber with 13-bone puppet + sprite-tilemap
13-bone humanoid rig (12 visible bones + 1 root) hand-ported from
substrate reference, mapped to PROTOTYPE asset-pack via asset_aliases
indirection (asset_pack: player). Bones use texture/z_order/scale/
anchor fields from the rig-format extension. Tracks split: lower for
legs + feet (walk animation), upper for root/body/head/shoulders/arms
(idle animation).

Animations:
- idle.anim.json: 2.0s loop on upper track, subtle body+head sway
- walk.anim.json: 0.6s loop on lower track, legs+feet cycle

Sprite-tilemap: 4-tile palette (floor_001-003 walkable, floor_004
as wall). Map content: 20x20 with wall-border and interior wall
blocks. tile_rotations parallel array exercises 90 and 180-degree
rotations on a handful of cells for visual rotation-pipeline
verification.

init.lua loads textures via asset_aliases lookup:
- maps.load_textures(aliases) resolves tilemap-tile atlas-ids
- puppet.load_rig(path, aliases) loads + resolves bone textures
- furniture textures preloaded at init (bed, bench, backpack) to
  avoid first-frame load stutter; rendered via engine.render.
  draw_sprite_transform in the draw hook

Camera follows puppet via per-frame camera.set_target. Headtrack:
head bone (look_at: true) rotates to face mouse world-position.

New SPOREL_CI=1 traces from render and init hooks:
- vagrant: render_frame_ok (per frame from render)
- vagrant: sprite_mode=on (once after first sprite-draw)
- vagrant: assets_loaded=14 (once after init: 7 puppet + 4 tile + 3 furniture)
2026-05-18 03:29:54 +02:00
Axel Meyer
161913795b feat: bump to v0.2.0 with asset_aliases for sprite-upgrade
Manifest changes:
- Version 0.1.0 -> 0.2.0
- New asset_aliases block: player + tiles + world all map to
  lib-asset.prototype-subterrain
- deps bumped: lib-core.maps 0.1.1 -> 0.1.2, lib-core.puppet
  0.1.0 -> 0.2.0
- New dep: lib-asset.prototype-subterrain 0.1.0

Rig, animations, tilemap, and init.lua updates land in follow-up
commits in this slice.
2026-05-18 03:25:28 +02:00
Axel Meyer
db8129e2fc chore: bump lib-core.maps to 0.1.2, lib-core.puppet to 0.2.0 2026-05-18 03:22:29 +02:00
Axel Meyer
f7b38d984e feat: add CI-hooks for render-hook + state-transition smoke
Two env-var-gated hooks (no-op in normal play):
- SPOREL_CI=1: emits 'vagrant: render_frame_ok' per frame from
  render() and 'vagrant: frame_avg_ms=N' after 60 frames.
- SPOREL_VAGRANT_PHASE1_DRIVE=1: scripted move-right input on
  frames 21-40, idle otherwise. Combined with SPOREL_CI=1 produces
  observable idle -> walk -> idle state cycle.

State-transition trace 'vagrant: state=<walk|idle>' emits exactly
once per actual change in set_walk_or_idle, so the smoke greps
don't get noise from per-frame repeats.

Fix camera.set_target_provider (absent from camera API) to use
camera.set_target(x, y) called per frame from M.update instead.
2026-05-17 20:30:48 +02:00
Axel Meyer
2817613490 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.
2026-05-17 20:21:31 +02:00