using Microsoft.Xna.Framework; using System; using Xunit; namespace SemiColinGames.Tests { public class GeometryTests { private void AssertVectorsEqual(Vector2 v1, Vector2 v2) { Assert.Equal(v1.X, v2.X, 5); Assert.Equal(v1.Y, v2.Y, 5); } [Fact] public void TestVector2Rotate() { Vector2 v = new Vector2(10, 0); AssertVectorsEqual(new Vector2(10, 0), v.Rotate(FMath.DegToRad(0))); AssertVectorsEqual(new Vector2(0, 10), v.Rotate(FMath.DegToRad(90))); AssertVectorsEqual(new Vector2(-10, 0), v.Rotate(FMath.DegToRad(180))); AssertVectorsEqual(new Vector2(0, -10), v.Rotate(FMath.DegToRad(270))); AssertVectorsEqual(new Vector2(10, 0), v.Rotate(FMath.DegToRad(360))); AssertVectorsEqual(new Vector2(0, 10), v.Rotate(FMath.DegToRad(450))); AssertVectorsEqual(new Vector2(0, -10), v.Rotate(FMath.DegToRad(-90))); AssertVectorsEqual(new Vector2(-10, 0), v.Rotate(FMath.DegToRad(-180))); AssertVectorsEqual(new Vector2(0, 10), v.Rotate(FMath.DegToRad(-270))); AssertVectorsEqual(new Vector2(10, 0), v.Rotate(FMath.DegToRad(-360))); AssertVectorsEqual(new Vector2(0, -10), v.Rotate(FMath.DegToRad(-450))); AssertVectorsEqual(new Vector2(7.0710678f, 7.0710678f), v.Rotate(FMath.DegToRad(45))); AssertVectorsEqual(new Vector2(8.6602540f, 5f), v.Rotate(FMath.DegToRad(30))); AssertVectorsEqual(new Vector2(5f, 8.6602540f), v.Rotate(FMath.DegToRad(60))); AssertVectorsEqual(new Vector2(-5f, 8.6602540f), v.Rotate(FMath.DegToRad(120))); AssertVectorsEqual(new Vector2(-8.6602540f, 5f), v.Rotate(FMath.DegToRad(150))); AssertVectorsEqual(new Vector2(7.0710678f, -7.0710678f), v.Rotate(FMath.DegToRad(-45))); AssertVectorsEqual(new Vector2(8.6602540f, -5f), v.Rotate(FMath.DegToRad(-30))); AssertVectorsEqual(new Vector2(5f, -8.6602540f), v.Rotate(FMath.DegToRad(-60))); AssertVectorsEqual(new Vector2(-5f, -8.6602540f), v.Rotate(FMath.DegToRad(-120))); AssertVectorsEqual(new Vector2(-8.6602540f, -5f), v.Rotate(FMath.DegToRad(-150))); } [Fact] public void TestIntersectSegmentNotColliding() { AABB box = new AABB(new Vector2(0, 0), new Vector2(8, 8)); Assert.Null(box.IntersectSegment(new Vector2(-16, -16), new Vector2(32, 0))); } [Fact] public void TestIntersectSegmentHit() { AABB box = new AABB(new Vector2(0, 0), new Vector2(8, 8)); var point = new Vector2(-16, 4); var delta = new Vector2(32, 0); Hit? maybeHit = box.IntersectSegment(point, delta); Assert.NotNull(maybeHit); Hit hit = (Hit) maybeHit; Assert.Equal(box, hit.Collider); Assert.Equal(0.25, hit.Time); Assert.Equal(point.X + delta.X * hit.Time, hit.Position.X); Assert.Equal(point.Y + delta.Y * hit.Time, hit.Position.Y); Assert.Equal((1.0f - hit.Time) * -delta.X, hit.Delta.X); Assert.Equal((1.0f - hit.Time) * -delta.Y, hit.Delta.Y); Assert.Equal(-1, hit.Normal.X); Assert.Equal(0, hit.Normal.Y); } [Fact] public void TestIntersectSegmentFromInsideBox() { AABB box = new AABB(new Vector2(0, 0), new Vector2(8, 8)); var point = new Vector2(-4, 4); var delta = new Vector2(32, 0); Hit? maybeHit = box.IntersectSegment(point, delta); Assert.NotNull(maybeHit); Hit hit = (Hit) maybeHit; Assert.Equal(box, hit.Collider); Assert.Equal(0.0, hit.Time); Assert.Equal(-4, hit.Position.X); Assert.Equal(4, hit.Position.Y); Assert.Equal(-delta.X, hit.Delta.X); Assert.Equal(-delta.Y, hit.Delta.Y); Assert.Equal(-1, hit.Normal.X); Assert.Equal(0, hit.Normal.Y); } [Fact] public void TestIntersectSegmentWithPadding() { AABB box = new AABB(new Vector2(0, 0), new Vector2(8, 8)); var point = new Vector2(-16, 4); var delta = new Vector2(32, 0); int padding = 4; Hit? maybeHit = box.IntersectSegment(point, delta, new Vector2(padding, padding)); Assert.NotNull(maybeHit); Hit hit = (Hit) maybeHit; Assert.Equal(box, hit.Collider); Assert.Equal(0.125, hit.Time); Assert.Equal(point.X + delta.X * hit.Time, hit.Position.X); Assert.Equal(point.Y + delta.Y * hit.Time, hit.Position.Y); Assert.Equal((1.0f - hit.Time) * -delta.X, hit.Delta.X); Assert.Equal((1.0f - hit.Time) * -delta.Y, hit.Delta.Y); Assert.Equal(-1, hit.Normal.X); Assert.Equal(0, hit.Normal.Y); } [Fact] public void TestIntersectSegmentFromTwoDirections() { AABB box = new AABB(new Vector2(0, 0), new Vector2(32, 32)); var farPos = new Vector2(64, 0); var farToNearDelta = new Vector2(-32, 0); Assert.Null(box.IntersectSegment(farPos, farToNearDelta)); var nearPos = new Vector2(32, 0); var nearToFarDelta = new Vector2(32, 0); Assert.Null(box.IntersectSegment(nearPos, nearToFarDelta)); } [Fact] public void TestIntersectSegmentXAxisAligned() { AABB box = new AABB(new Vector2(0, 0), new Vector2(16, 16)); var pos = new Vector2(-32, 0); var delta = new Vector2(64, 0); Hit? maybeHit = box.IntersectSegment(pos, delta); Assert.NotNull(maybeHit); Hit hit = (Hit) maybeHit; Assert.Equal(0.25, hit.Time); Assert.Equal(-1, hit.Normal.X); Assert.Equal(0, hit.Normal.Y); } [Fact] public void TestIntersectSegmentYAxisAligned() { AABB box = new AABB(new Vector2(0, 0), new Vector2(16, 16)); var pos = new Vector2(0, -32); var delta = new Vector2(0, 64); Hit? maybeHit = box.IntersectSegment(pos, delta); Assert.NotNull(maybeHit); Hit hit = (Hit) maybeHit; Assert.Equal(0.25, hit.Time); Assert.Equal(0, hit.Normal.X); Assert.Equal(-1, hit.Normal.Y); } } }