feat(puppet): v0.3.0 — idle-return locomotion + version bump
- apply_locomotion idle-return: after (now - last_move_time) > idle_return_delay, the most-displaced planted leg steps back to its current hip position (over idle_step_duration). Group-stagger via bumping last_move_time forward by idle_return_stagger. - M.move_to tracks p.last_move_time when position actually changes. - README v0.3.0 changelog entry.
This commit is contained in:
17
README.md
17
README.md
@@ -5,7 +5,7 @@ tracks, rest pose, keyframe animations, procedural animations
|
||||
(Lua-side), and look-at constraint. No footplant IK in v0.1
|
||||
(deferred).
|
||||
|
||||
**Version:** 0.2.0
|
||||
**Version:** 0.3.0
|
||||
**Lib-ID:** lib-core.puppet
|
||||
**Requires:** (none — pure Lua + engine.render.*)
|
||||
**Tags:** animation, skeleton, puppet, character
|
||||
@@ -125,6 +125,21 @@ ownership at write time.
|
||||
|
||||
## CHANGELOG
|
||||
|
||||
### v0.3.0
|
||||
- BoneState multi-channel (rot/pos/scl) with world.scl_x/y and world.rot
|
||||
- Cascaded world-transform with scale propagation (compute_world)
|
||||
- Procedural locomotion layer via rig.locomotion block (apply_locomotion):
|
||||
step-trigger, step-placement, step-height, leg-aim + leg-stretch
|
||||
- Idle-return logic in apply_locomotion: after (now - last_move_time) >
|
||||
idle_return_delay, the most-displaced planted leg steps back to its hip
|
||||
position over idle_step_duration; group-stagger via idle_return_stagger
|
||||
- M.move_to tracks p.last_move_time when position actually changes
|
||||
- Schema changes: rest.rot/scl required; legacy rest.angle rejected with
|
||||
clear error message (Substrate-Parity v0.3.0 schema)
|
||||
- Bone-rig top-level scale field removed; per-frame world state replaces it
|
||||
- New APIs: bone_world_scale, set_foot_sprite_reach_test_only,
|
||||
foot_state_test_only, bone_animated_test_only
|
||||
|
||||
### v0.2.0
|
||||
- Rig-format extension (texture, z_order, scale, anchor, asset_pack
|
||||
fields on bones; rig.bones_z_sorted for render-order)
|
||||
|
||||
36
init.lua
36
init.lua
@@ -438,6 +438,7 @@ function M.move_to(handle, x, y)
|
||||
p.facing = math.atan(dy, dx)
|
||||
p.last_move_x = x
|
||||
p.last_move_y = y
|
||||
p.last_move_time = engine.time.now()
|
||||
end
|
||||
p.x = x
|
||||
p.y = y
|
||||
@@ -731,6 +732,41 @@ local function apply_locomotion(p, dt)
|
||||
|
||||
::continue::
|
||||
end
|
||||
|
||||
if (now - p.last_move_time) > loco.idle_return_delay then
|
||||
local any_stepping = false
|
||||
for i, _ in ipairs(loco.legs) do
|
||||
if p.foot_state[i].state ~= "planted" then any_stepping = true; break end
|
||||
end
|
||||
if not any_stepping then
|
||||
local best_i, best_dist = nil, 0
|
||||
for i, leg_def in ipairs(loco.legs) do
|
||||
local fs = p.foot_state[i]
|
||||
if fs.state == "planted" then
|
||||
local hip_wx = p.bone_state[leg_def.leg].world.x
|
||||
local hip_wy = p.bone_state[leg_def.leg].world.y
|
||||
local d = math.sqrt((hip_wx - fs.anchor_x)^2 + (hip_wy - fs.anchor_y)^2)
|
||||
if d > best_dist then
|
||||
best_dist = d
|
||||
best_i = i
|
||||
end
|
||||
end
|
||||
end
|
||||
if best_i and best_dist > 1 then
|
||||
local fs = p.foot_state[best_i]
|
||||
local hip_wx = p.bone_state[loco.legs[best_i].leg].world.x
|
||||
local hip_wy = p.bone_state[loco.legs[best_i].leg].world.y
|
||||
fs.state = "stepping"
|
||||
fs.step_from_x = fs.cur_x
|
||||
fs.step_from_y = fs.cur_y
|
||||
fs.step_to_x = hip_wx
|
||||
fs.step_to_y = hip_wy
|
||||
fs.step_timer = 0
|
||||
fs.step_total = loco.idle_step_duration
|
||||
p.last_move_time = now - loco.idle_return_delay + loco.idle_return_stagger
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- ====================================================================
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"id": "lib-core.puppet",
|
||||
"version": "0.2.0",
|
||||
"version": "0.3.0",
|
||||
"api_min": "0.1",
|
||||
"deps": []
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user