From 0a7ef7f270bc955599a79089f05d614733aa510f Mon Sep 17 00:00:00 2001 From: Axel Meyer Date: Mon, 18 May 2026 21:48:10 +0200 Subject: [PATCH] fix(vagrant): legs rotate to walk direction (user preference) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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). --- init.lua | 29 +++++++++++++++-------------- manifest.module | 2 +- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/init.lua b/init.lua index b104881..118f497 100644 --- a/init.lua +++ b/init.lua @@ -71,11 +71,18 @@ local function pick_walk_anim(num_deg) end end --- HandleAnimationLower port: chooses walk anim based on signed angle between --- body-forward and move-direction. Manages idle_lower / walk_* transitions. +-- Lower-body controller: legs rotate to walk direction (NOT Substrate's +-- body-relative wedge). User preference: leg stride visually aligns with +-- movement axis. lower_control.rot = atan(move_x, -move_y) so leg sprites +-- (which oscillate scl_y along their local Y) cycle along the walk axis. +-- One generic walk_fwd_lower anim suffices since the rotation handles +-- the directional change (4-direction anims kept on disk for future +-- gait-style differentiation). local function update_lower_anim(moving, move_x, move_y) if not moving then - -- Idle: stop all walk anims, resume idle_lower. + -- Idle: stop walk anims, resume idle_lower. Preserve last + -- lower_control_rot_deg so legs keep their last orientation + -- (no snap-back to north on stop). if state.walk_anim_current ~= nil then for _, a in ipairs(WALK_ANIMS) do puppet.stop(state.player, a) @@ -91,22 +98,16 @@ local function update_lower_anim(moving, move_x, move_y) ci_last_state = "idle" end end - state.lower_control_rot_deg = 0 return end - -- Walking: read body's previous-frame world.rot for signed angle computation. - local _, _, body_rot = puppet.bone_world_transform(state.player, "body") - -- Body forward direction (sprite-top-up convention): forward = -Y at rot=0. - -- In world coords: fwd_x = sin(rot), fwd_y = -cos(rot). - local fwd_x = math.sin(body_rot) - local fwd_y = -math.cos(body_rot) - local num = signed_angle_2d(fwd_x, fwd_y, move_x, move_y) - local anim_id, wedge_deg = pick_walk_anim(num) - state.lower_control_rot_deg = wedge_deg + -- Walking: legs face walk direction (sprite-top convention: rot=0 = -Y). + state.lower_control_rot_deg = math.deg(math.atan(move_x, -move_y)) + -- Single generic walk anim (4-direction-picker deferred until we have + -- differentiated gait styles per direction). + local anim_id = "walk_fwd_lower" if state.walk_anim_current ~= anim_id then - -- Swap to new walk anim. for _, a in ipairs(WALK_ANIMS) do if a ~= anim_id then puppet.stop(state.player, a) end end diff --git a/manifest.module b/manifest.module index cf99157..a5fd30e 100644 --- a/manifest.module +++ b/manifest.module @@ -15,7 +15,7 @@ {"id": "lib-core.camera", "version": "0.3.0"}, {"id": "lib-core.render", "version": "0.1.0"}, {"id": "lib-core.maps", "version": "0.1.2"}, - {"id": "lib-core.puppet", "version": "0.4.0"}, + {"id": "lib-core.puppet", "version": "0.4.1"}, {"id": "lib-asset.prototype-subterrain", "version": "0.1.1"} ] }