feat(client): 3D locomotion sandbox — character walks the live Gauntlet (T-1088)
New SR_LIVE sandbox scene: CharacterVisual composited in a 3D greybox world derived from server snapshots. Per-leg constant-velocity interpolation keyed to the stance throttle, 'server feet / client eyes' facing (wire octant while moving, client aim octant idle), cadence-synced gait state machine on AnimationPlayer custom blends, D-148 orthographic follow camera (-30deg default, T-cycle presets), sim-space grid shader, camera-side wall cutaway, accumulating never-evict tile store with four-state visibility tint. Additive seams only: InputMapper.facing_angle_provider (2D path unchanged), CharacterVisual.play_animation blend_time param + get_animation_player(). Visual harness gains per-scenario scene field + SR_AUTOPILOT input scripting. 210 new gdUnit assertions across five suites; verified live (230/230 total, clean smoke, screenshot at .cache/screenshots/locomotion_idle_live.png). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -59,6 +59,13 @@ var facing_octant: String = "North" # Derived from facing_angle
|
||||
var _last_sent_octant: String = "North" # Track to avoid redundant sends
|
||||
var _last_move_msec: int = 0
|
||||
|
||||
# T-1088 (design §9): 3D facing seam. A 3D scene installs a provider returning
|
||||
# sim-space radians (0=East, +PI/2=South — same convention as facing_angle), or
|
||||
# NAN = no update (deadzone/degenerate ray). While installed it fully replaces the
|
||||
# 2D canvas-transform path in _update_facing_from_mouse(); unset (default) leaves
|
||||
# the 2D path unchanged. Untyped Callable per the autoload parse-order rule.
|
||||
var facing_angle_provider = Callable()
|
||||
|
||||
|
||||
# Hold-to-move: poll held direction keys each frame, throttled by stance.
|
||||
# D-054: WASD is now mouse-relative. W = toward cursor, A/D = strafe.
|
||||
@@ -180,6 +187,16 @@ func reset_facing_state() -> void:
|
||||
# Intentional coupling: reads GameState.player_position directly — InputMapper is an
|
||||
# autoload that runs before game loop rendering, so position is always current-tick.
|
||||
func _update_facing_from_mouse() -> void:
|
||||
# T-1088 (design §9): provider seam. In a 3D scene the canvas-transform anchor
|
||||
# below is a far-off-screen point, and the screen-space mouse angle is not a
|
||||
# sim-space angle under the 45° map rotation + ortho pitch — an installed
|
||||
# provider (e.g. SandboxMouseAimProvider) replaces this whole path.
|
||||
if facing_angle_provider.is_valid():
|
||||
var a: float = facing_angle_provider.call()
|
||||
if is_finite(a):
|
||||
facing_angle = a
|
||||
facing_octant = _angle_to_octant(a)
|
||||
return
|
||||
var vp := get_viewport()
|
||||
if vp == null:
|
||||
return
|
||||
|
||||
Reference in New Issue
Block a user