neon-sprawl/client/test/player_locomotion_wasd_test.gd

116 lines
4.0 KiB
GDScript

# Pure helpers on res://scripts/player_locomotion_wasd.gd (NEO-22 WASD seam math).
extends GdUnitTestSuite
const PlayerLocomotionWasdScript := preload("res://scripts/player_locomotion_wasd.gd")
func test_evaluate_floor_ray_hit_y_rejects_hit_too_far_below_feet() -> void:
var feet_y := 0.0
var hit_y := feet_y - 0.2
var n := Vector3.UP
var out: float = PlayerLocomotionWasdScript.evaluate_floor_ray_hit_y(
feet_y, hit_y, n, 0.108, 0.42
)
assert_that(out).is_equal(PlayerLocomotionWasdScript.FLOOR_RAY_FEET_INVALID)
func test_evaluate_floor_ray_hit_y_rejects_shallow_floor_normal() -> void:
var feet_y := 0.0
var hit_y := 0.0
# Up component ~0.37 so dot(Vector3.UP, n) is below min_floor_up_dot (0.42).
var n := Vector3(0.85, 0.35, 0.0).normalized()
var out: float = PlayerLocomotionWasdScript.evaluate_floor_ray_hit_y(
feet_y, hit_y, n, 0.108, 0.42
)
assert_that(out).is_equal(PlayerLocomotionWasdScript.FLOOR_RAY_FEET_INVALID)
func test_evaluate_floor_ray_hit_y_accepts_valid_hit() -> void:
var feet_y := 0.0
var hit_y := -0.04
var n := Vector3.UP
var out: float = PlayerLocomotionWasdScript.evaluate_floor_ray_hit_y(
feet_y, hit_y, n, 0.108, 0.42
)
assert_that(out).is_equal(hit_y)
func test_median_feet_y_from_samples_empty_is_invalid() -> void:
var empty: Array[float] = []
var out: float = PlayerLocomotionWasdScript.median_feet_y_from_samples(empty)
assert_that(out).is_equal(PlayerLocomotionWasdScript.FLOOR_RAY_FEET_INVALID)
func test_median_feet_y_from_samples_single() -> void:
var out: float = PlayerLocomotionWasdScript.median_feet_y_from_samples([0.12])
assert_that(out).is_equal(0.12)
func test_median_feet_y_from_samples_three_sorted_middle() -> void:
var out: float = PlayerLocomotionWasdScript.median_feet_y_from_samples([0.3, 0.1, 0.2])
assert_that(out).is_equal(0.2)
func test_median_feet_y_from_samples_two_uses_lower_index() -> void:
# Matches runtime: mid index (n-1)>>1 picks the smaller of two sorted values.
var out: float = PlayerLocomotionWasdScript.median_feet_y_from_samples([0.5, 0.1])
assert_that(out).is_equal(0.1)
func test_xz_after_micro_slip_projection_zero_wish_unchanged() -> void:
var anchor := Vector2.ZERO
var player_xz := Vector2(0.02, 0.03)
var out: Vector2 = PlayerLocomotionWasdScript.xz_after_micro_slip_projection(
anchor, player_xz, Vector2.ZERO, 0.032
)
assert_that(out).is_equal(player_xz)
func test_xz_after_micro_slip_projection_large_perp_unchanged() -> void:
var anchor := Vector2.ZERO
var player_xz := Vector2(0.0, 0.2)
var wish := Vector2(1.0, 0.0)
var out: Vector2 = PlayerLocomotionWasdScript.xz_after_micro_slip_projection(
anchor, player_xz, wish, 0.032
)
assert_that(out).is_equal(player_xz)
func test_xz_after_micro_slip_projection_nudges_small_perp() -> void:
var anchor := Vector2.ZERO
var player_xz := Vector2(0.0, 0.01)
var wish := Vector2(1.0, 0.0)
var out: Vector2 = PlayerLocomotionWasdScript.xz_after_micro_slip_projection(
anchor, player_xz, wish, 0.032
)
assert_that(out.x).is_equal(0.0)
assert_that(out.y).is_equal(0.0)
func test_horizontal_velocity_aligned_to_wish_zero_wish_returns_velocity() -> void:
var out: Vector2 = PlayerLocomotionWasdScript.horizontal_velocity_aligned_to_wish(
Vector2.ZERO, Vector2(3.0, 4.0), 5.0
)
assert_that(out).is_equal(Vector2(3.0, 4.0))
func test_horizontal_velocity_aligned_to_wish_clamps_negative_along_to_zero() -> void:
var out: Vector2 = PlayerLocomotionWasdScript.horizontal_velocity_aligned_to_wish(
Vector2(1.0, 0.0), Vector2(-2.0, 0.0), 5.0
)
assert_that(out).is_equal(Vector2.ZERO)
func test_horizontal_velocity_aligned_to_wish_caps_speed() -> void:
var out: Vector2 = PlayerLocomotionWasdScript.horizontal_velocity_aligned_to_wish(
Vector2(1.0, 0.0), Vector2(10.0, 0.0), 5.0
)
assert_that(out).is_equal(Vector2(5.0, 0.0))
func test_horizontal_velocity_aligned_to_wish_preserves_wish_direction() -> void:
var out: Vector2 = PlayerLocomotionWasdScript.horizontal_velocity_aligned_to_wish(
Vector2(0.0, 1.0), Vector2(0.0, 2.0), 5.0
)
assert_that(out).is_equal(Vector2(0.0, 2.0))