using GameCli; using Xunit; namespace GameCli.Tests; public class PhysicsTests { [Fact] public void Noop_UnderGravity_ShipFallsDownward() { var start = new ShipState(0.5f, 0.5f, 0f, 0f, 0f, 0f); var next = Physics.Step(start, action: 0); Assert.True(next.VY > 0, $"expected VY > 0 (gravity down), got {next.VY}"); Assert.True(next.Y > start.Y, $"expected Y to increase (fall), got {next.Y}"); Assert.Equal(start.X, next.X, precision: 5); Assert.Equal(0f, next.Angle); } [Fact] public void MainEngine_WhenUpright_CancelsThenReversesGravity() { // Main engine thrust > gravity, so acceleration is net upward (VY becomes negative). var start = new ShipState(0.5f, 0.5f, 0f, 0f, 0f, 0f); var next = Physics.Step(start, action: 2); Assert.True(next.VY < 0, $"expected VY < 0 (net upward), got {next.VY}"); } [Fact] public void LeftThruster_AppliesNegativeTorque() { var start = new ShipState(0.5f, 0.5f, 0f, 0f, 0f, 0f); var next = Physics.Step(start, action: 1); Assert.True(next.AngularVelocity < 0, $"expected angular velocity < 0, got {next.AngularVelocity}"); } [Fact] public void RightThruster_AppliesPositiveTorque() { var start = new ShipState(0.5f, 0.5f, 0f, 0f, 0f, 0f); var next = Physics.Step(start, action: 3); Assert.True(next.AngularVelocity > 0, $"expected angular velocity > 0, got {next.AngularVelocity}"); } [Fact] public void MainEngine_WhenRotated90Right_ThrustsRight() { // Angle = +pi/2 means ship points to the +x direction (right). // Main engine pushes along body-up, which is now world +x. var start = new ShipState(0.5f, 0.5f, 0f, 0f, MathF.PI / 2f, 0f); var next = Physics.Step(start, action: 2); Assert.True(next.VX > 0, $"expected VX > 0 (thrust right), got {next.VX}"); } [Fact] public void Step_IsDeterministic() { var start = new ShipState(0.3f, 0.4f, 0.1f, -0.05f, 0.2f, 0.3f); var a = Physics.Step(start, action: 2); var b = Physics.Step(start, action: 2); Assert.Equal(a, b); } }