using System; using System.Numerics; using AcDream.App.Input; using AcDream.Core.Physics; using Xunit; namespace AcDream.Core.Tests.Input; public class PlayerMovementControllerTests { private static PhysicsEngine MakeFlatEngine() { var engine = new PhysicsEngine(); var heights = new byte[81]; Array.Fill(heights, (byte)50); var heightTable = new float[256]; for (int i = 0; i < 256; i++) heightTable[i] = i * 1f; var terrain = new TerrainSurface(heights, heightTable); engine.AddLandblock(0xA9B4FFFFu, terrain, Array.Empty(), worldOffsetX: 0f, worldOffsetY: 0f); return engine; } [Fact] public void Update_NoInput_PositionUnchanged() { var engine = MakeFlatEngine(); var controller = new PlayerMovementController(engine); controller.SetPosition(new Vector3(96f, 96f, 50f), 0x0001); var result = controller.Update(0.016f, new MovementInput()); Assert.Equal(96f, result.Position.X, precision: 1); Assert.Equal(96f, result.Position.Y, precision: 1); } [Fact] public void Update_ForwardInput_MovesInFacingDirection() { var engine = MakeFlatEngine(); var controller = new PlayerMovementController(engine); controller.SetPosition(new Vector3(96f, 96f, 50f), 0x0001); controller.Yaw = 0f; // facing +X var input = new MovementInput { Forward = true }; var result = controller.Update(1.0f, input); // 1 second // Should have moved ~4 units in +X (walk speed). Assert.True(result.Position.X > 96f + 2f, $"X={result.Position.X} should have moved forward"); } [Fact] public void Update_RunForward_MoveFasterThanWalk() { var engine = MakeFlatEngine(); var controller = new PlayerMovementController(engine); controller.SetPosition(new Vector3(96f, 96f, 50f), 0x0001); controller.Yaw = 0f; var walkInput = new MovementInput { Forward = true }; var walkResult = controller.Update(1.0f, walkInput); float walkDist = walkResult.Position.X - 96f; controller.SetPosition(new Vector3(96f, 96f, 50f), 0x0001); var runInput = new MovementInput { Forward = true, Run = true }; var runResult = controller.Update(1.0f, runInput); float runDist = runResult.Position.X - 96f; Assert.True(runDist > walkDist, $"Run ({runDist}) should be faster than walk ({walkDist})"); } [Fact] public void Update_TurnInput_ChangesYaw() { var engine = MakeFlatEngine(); var controller = new PlayerMovementController(engine); controller.SetPosition(new Vector3(96f, 96f, 50f), 0x0001); float initialYaw = controller.Yaw; var input = new MovementInput { TurnRight = true }; controller.Update(0.5f, input); Assert.NotEqual(initialYaw, controller.Yaw); } [Fact] public void MotionStateChanged_WhenStartingToWalk() { var engine = MakeFlatEngine(); var controller = new PlayerMovementController(engine); controller.SetPosition(new Vector3(96f, 96f, 50f), 0x0001); // First frame: idle (no input). controller.Update(0.016f, new MovementInput()); // Second frame: start walking. var input = new MovementInput { Forward = true }; var result = controller.Update(0.016f, input); Assert.True(result.MotionStateChanged); } }