commit
						5ddea72d72
					
				|  | @ -3,7 +3,7 @@ version: 2.1 | ||||||
| defaults: &defaults | defaults: &defaults | ||||||
|   working_directory: ~/repo |   working_directory: ~/repo | ||||||
|   docker: |   docker: | ||||||
|     - image: mcr.microsoft.com/dotnet/core/sdk:2.2 |     - image: mcr.microsoft.com/dotnet/core/sdk:3.0 | ||||||
|       environment: |       environment: | ||||||
|         DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 1 |         DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 1 | ||||||
|         DOTNET_CLI_TELEMETRY_OPTOUT: 1 |         DOTNET_CLI_TELEMETRY_OPTOUT: 1 | ||||||
|  |  | ||||||
|  | @ -1,2 +1,3 @@ | ||||||
| bin/ | bin/ | ||||||
| obj/ | obj/ | ||||||
|  | .vscode | ||||||
|  | @ -16,5 +16,7 @@ | ||||||
|   </PropertyGroup> |   </PropertyGroup> | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|     <PackageReference Include="MoonTools.Core.Structs" Version="1.0.1"/> |     <PackageReference Include="MoonTools.Core.Structs" Version="1.0.1"/> | ||||||
|  |     <PackageReference Include="morelinq" Version="3.2.0"/> | ||||||
|  |     <PackageReference Include="Collections.Pooled" Version="1.0.82"/> | ||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
| </Project> | </Project> | ||||||
|  | @ -0,0 +1,36 @@ | ||||||
|  | using System; | ||||||
|  | using Microsoft.Xna.Framework; | ||||||
|  | using MoonTools.Core.Structs; | ||||||
|  | 
 | ||||||
|  | namespace MoonTools.Core.Bonk | ||||||
|  | { | ||||||
|  |     public struct MinkowskiDifference : IEquatable<MinkowskiDifference> | ||||||
|  |     { | ||||||
|  |         private IShape2D shapeA; | ||||||
|  |         private Transform2D transformA; | ||||||
|  |         private IShape2D shapeB; | ||||||
|  |         private Transform2D transformB; | ||||||
|  | 
 | ||||||
|  |         public MinkowskiDifference(IShape2D shapeA, Transform2D transformA, IShape2D shapeB, Transform2D transformB) | ||||||
|  |         { | ||||||
|  |             this.shapeA = shapeA; | ||||||
|  |             this.transformA = transformA; | ||||||
|  |             this.shapeB = shapeB; | ||||||
|  |             this.transformB = transformB; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public bool Equals(MinkowskiDifference other) | ||||||
|  |         { | ||||||
|  |             return | ||||||
|  |                 shapeA == other.shapeA && | ||||||
|  |                 transformA.Equals(other.transformA) && | ||||||
|  |                 shapeB == other.shapeB && | ||||||
|  |                 transformB.Equals(other.transformB); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public Vector2 Support(Vector2 direction) | ||||||
|  |         { | ||||||
|  |             return shapeA.Support(direction, transformA) - shapeB.Support(-direction, transformB); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -4,10 +4,10 @@ | ||||||
|  * https://blog.hamaluik.ca/posts/building-a-collision-engine-part-2-2d-penetration-vectors/ |  * https://blog.hamaluik.ca/posts/building-a-collision-engine-part-2-2d-penetration-vectors/ | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
|  | using Collections.Pooled; | ||||||
| using Microsoft.Xna.Framework; | using Microsoft.Xna.Framework; | ||||||
| using MoonTools.Core.Structs; | using MoonTools.Core.Structs; | ||||||
| using System; | using System; | ||||||
| using System.Collections.Generic; |  | ||||||
| 
 | 
 | ||||||
| namespace MoonTools.Core.Bonk | namespace MoonTools.Core.Bonk | ||||||
| { | { | ||||||
|  | @ -20,11 +20,11 @@ namespace MoonTools.Core.Bonk | ||||||
|     public static class EPA2D |     public static class EPA2D | ||||||
|     { |     { | ||||||
|         // vector returned gives direction from A to B |         // vector returned gives direction from A to B | ||||||
|         public static Vector2 Intersect(IShape2D shapeA, Transform2D Transform2DA, IShape2D shapeB, Transform2D Transform2DB, IEnumerable<Vector2> givenSimplexVertices) |         public static Vector2 Intersect(IShape2D shapeA, Transform2D Transform2DA, IShape2D shapeB, Transform2D Transform2DB, Simplex simplex) | ||||||
|         { |         { | ||||||
|             var simplexVertices = new SimplexVertices(new Vector2?[36]); |             var simplexVertices = new PooledList<Vector2>(36, ClearMode.Always); | ||||||
| 
 | 
 | ||||||
|             foreach (var vertex in givenSimplexVertices) |             foreach (var vertex in simplex.Vertices) | ||||||
|             { |             { | ||||||
|                 simplexVertices.Add(vertex); |                 simplexVertices.Add(vertex); | ||||||
|             } |             } | ||||||
|  | @ -55,10 +55,12 @@ namespace MoonTools.Core.Bonk | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|  |             simplexVertices.Dispose(); | ||||||
|  | 
 | ||||||
|             return intersection; |             return intersection; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         private static Edge FindClosestEdge(PolygonWinding winding, SimplexVertices simplexVertices) |         private static Edge FindClosestEdge(PolygonWinding winding, PooledList<Vector2> simplexVertices) | ||||||
|         { |         { | ||||||
|             var closestDistance = float.PositiveInfinity; |             var closestDistance = float.PositiveInfinity; | ||||||
|             var closestNormal = Vector2.Zero; |             var closestNormal = Vector2.Zero; | ||||||
|  |  | ||||||
|  | @ -1,126 +1,77 @@ | ||||||
| /* | using Microsoft.Xna.Framework; | ||||||
|  * Implementation of the GJK collision algorithm |  | ||||||
|  * Based on some math blogs |  | ||||||
|  * https://blog.hamaluik.ca/posts/building-a-collision-engine-part-1-2d-gjk-collision-detection/ |  | ||||||
|  * and some code from https://github.com/kroitor/gjk.c |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| using Microsoft.Xna.Framework; |  | ||||||
| using MoonTools.Core.Structs; | using MoonTools.Core.Structs; | ||||||
| using System; | using MoonTools.Core.Bonk.Extensions; | ||||||
| 
 | 
 | ||||||
| namespace MoonTools.Core.Bonk | namespace MoonTools.Core.Bonk | ||||||
| { | { | ||||||
|     public static class GJK2D |     public static class GJK2D | ||||||
|     { |     { | ||||||
|         private enum SolutionStatus |         public static bool TestCollision(IShape2D shapeA, Transform2D transformA, IShape2D shapeB, Transform2D transformB) | ||||||
|         { |         { | ||||||
|             NoIntersection, |             var minkowskiDifference = new MinkowskiDifference(shapeA, transformA, shapeB, transformB); | ||||||
|             Intersection, |             var a = minkowskiDifference.Support(Vector2.UnitX); | ||||||
|             StillSolving |             var b = minkowskiDifference.Support(-a); | ||||||
|  | 
 | ||||||
|  |             return Vector2.Dot(a, b) > 0 ? false : CheckSimplex(new Simplex(minkowskiDifference, a, b)); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         public static ValueTuple<bool, SimplexVertices> TestCollision(IShape2D shapeA, Transform2D Transform2DA, IShape2D shapeB, Transform2D Transform2DB) |         private static bool CheckSimplex(Simplex simplex) | ||||||
|         { |         { | ||||||
|             var vertices = new SimplexVertices(new Vector2?[] { null, null, null, null }); |             var a = simplex.DirectionA; | ||||||
|  |             var b = simplex.DirectionB; | ||||||
| 
 | 
 | ||||||
|             const SolutionStatus solutionStatus = SolutionStatus.StillSolving; |             var axb = a.Cross(b); | ||||||
|             var direction = Transform2DB.Position - Transform2DA.Position; |             var c = simplex.Support((b - a).Perpendicular()); | ||||||
|  |             var axc = a.Cross(c); | ||||||
|  |             var bxc = b.Cross(c); | ||||||
|  |             var cxb = -bxc; | ||||||
| 
 | 
 | ||||||
|             var result = (solutionStatus, direction); |             return (b - a) == Vector2.Zero || (axb.Y > 0 != bxc.Y > 0 ? CheckSimplex(simplex.WithDirections(b, c)) : (axc.Y > 0 != cxb.Y > 0 ? CheckSimplex(simplex.WithDirections(a, c)) : true)); | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|             while (result.solutionStatus == SolutionStatus.StillSolving) |         public static (bool, Simplex) FindCollisionSimplex(IShape2D shapeA, Transform2D transformA, IShape2D shapeB, Transform2D transformB) | ||||||
|  |         { | ||||||
|  |             var minkowskiDifference = new MinkowskiDifference(shapeA, transformA, shapeB, transformB); | ||||||
|  |             var a = minkowskiDifference.Support(Vector2.UnitX); | ||||||
|  |             var b = minkowskiDifference.Support(-a); | ||||||
|  | 
 | ||||||
|  |             return Vector2.Dot(a, b) > 0 ? (false, default(Simplex)) : Simplex(new Simplex(minkowskiDifference, a, b)); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         private static (bool, Simplex) Simplex(Simplex simplex) | ||||||
|  |         { | ||||||
|  |             var a = simplex.DirectionA; | ||||||
|  |             var b = simplex.DirectionB; | ||||||
|  | 
 | ||||||
|  |             if ((b - a) == Vector2.Zero) | ||||||
|             { |             { | ||||||
|                 result = EvolveSimplex(shapeA, Transform2DA, shapeB, Transform2DB, vertices, result.direction); |                 return (false, simplex.WithDirections(a, b)); | ||||||
|             } |             } | ||||||
| 
 |             else | ||||||
|             return ValueTuple.Create(result.solutionStatus == SolutionStatus.Intersection, vertices); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         private static (SolutionStatus, Vector2) EvolveSimplex(IShape2D shapeA, Transform2D Transform2DA, IShape2D shapeB, Transform2D Transform2DB, SimplexVertices vertices, Vector2 direction) |  | ||||||
|         { |  | ||||||
|             switch(vertices.Count) |  | ||||||
|             { |             { | ||||||
|                 case 0: |                 var c = simplex.Support((b - a).Perpendicular()); | ||||||
|                     if (direction == Vector2.Zero) |                 var axb = a.Cross(b); | ||||||
|  |                 var bxc = b.Cross(c); | ||||||
|  | 
 | ||||||
|  |                 if (axb.Y > 0 != bxc.Y > 0) | ||||||
|  |                 { | ||||||
|  |                     return Simplex(simplex.WithDirections(b, c)); | ||||||
|  |                 } | ||||||
|  |                 else | ||||||
|  |                 { | ||||||
|  |                     var axc = a.Cross(c); | ||||||
|  |                     var cxb = -bxc; | ||||||
|  | 
 | ||||||
|  |                     if (axc.Y > 0 != cxb.Y > 0) | ||||||
|                     { |                     { | ||||||
|                         direction = Vector2.UnitX; |                         return Simplex(simplex.WithDirections(a, b)); | ||||||
|                     } |                     } | ||||||
|                     break; |  | ||||||
| 
 |  | ||||||
|                 case 1: |  | ||||||
|                     direction *= -1; |  | ||||||
|                     break; |  | ||||||
| 
 |  | ||||||
|                 case 2: |  | ||||||
|                     var ab = vertices[1] - vertices[0]; |  | ||||||
|                     var a0 = vertices[0] * -1; |  | ||||||
| 
 |  | ||||||
|                     direction = TripleProduct(ab, a0, ab); |  | ||||||
|                     if (direction == Vector2.Zero) |  | ||||||
|                     { |  | ||||||
|                         direction = Perpendicular(ab); |  | ||||||
|                     } |  | ||||||
|                     break; |  | ||||||
| 
 |  | ||||||
|                 case 3: |  | ||||||
|                     var c0 = vertices[2] * -1; |  | ||||||
|                     var bc = vertices[1] - vertices[2]; |  | ||||||
|                     var ca = vertices[0] - vertices[2]; |  | ||||||
| 
 |  | ||||||
|                     var bcNorm = TripleProduct(ca, bc, bc); |  | ||||||
|                     var caNorm = TripleProduct(bc, ca, ca); |  | ||||||
| 
 |  | ||||||
|                     // the origin is outside line bc |  | ||||||
|                     // get rid of a and add a new support in the direction of bcNorm |  | ||||||
|                     if (Vector2.Dot(bcNorm, c0) > 0) |  | ||||||
|                     { |  | ||||||
|                         vertices.RemoveAt(0); |  | ||||||
|                         direction = bcNorm; |  | ||||||
|                     } |  | ||||||
|                     // the origin is outside line ca |  | ||||||
|                     // get rid of b and add a new support in the direction of caNorm |  | ||||||
|                     else if (Vector2.Dot(caNorm, c0) > 0) |  | ||||||
|                     { |  | ||||||
|                         vertices.RemoveAt(1); |  | ||||||
|                         direction = caNorm; |  | ||||||
|                     } |  | ||||||
|                     // the origin is inside both ab and ac, |  | ||||||
|                     // so it must be inside the triangle! |  | ||||||
|                     else |                     else | ||||||
|                     { |                     { | ||||||
|                         return (SolutionStatus.Intersection, direction); |                         return (true, simplex.WithDirections(a, b)); | ||||||
|                     } |                     } | ||||||
|                     break; |                 } | ||||||
|             } |             } | ||||||
| 
 |  | ||||||
|             return (AddSupport(shapeA, Transform2DA, shapeB, Transform2DB, vertices, direction) ? |  | ||||||
|                 SolutionStatus.StillSolving : |  | ||||||
|                 SolutionStatus.NoIntersection, direction); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         private static bool AddSupport(IShape2D shapeA, Transform2D Transform2DA, IShape2D shapeB, Transform2D Transform2DB, SimplexVertices vertices, Vector2 direction) |  | ||||||
|         { |  | ||||||
|             var newVertex = shapeA.Support(direction, Transform2DA) - shapeB.Support(-direction, Transform2DB); |  | ||||||
|             vertices.Add(newVertex); |  | ||||||
|             return Vector2.Dot(direction, newVertex) >= 0; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         private static Vector2 TripleProduct(Vector2 a, Vector2 b, Vector2 c) |  | ||||||
|         { |  | ||||||
|             var A = new Vector3(a.X, a.Y, 0); |  | ||||||
|             var B = new Vector3(b.X, b.Y, 0); |  | ||||||
|             var C = new Vector3(c.X, c.Y, 0); |  | ||||||
| 
 |  | ||||||
|             var first = Vector3.Cross(A, B); |  | ||||||
|             var second = Vector3.Cross(first, C); |  | ||||||
| 
 |  | ||||||
|             return new Vector2(second.X, second.Y); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         private static Vector2 Perpendicular(Vector2 v) |  | ||||||
|         { |  | ||||||
|             return new Vector2(v.Y, -v.X); |  | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1,91 +0,0 @@ | ||||||
| using System; |  | ||||||
| using System.Collections; |  | ||||||
| using System.Collections.Generic; |  | ||||||
| using Microsoft.Xna.Framework; |  | ||||||
| 
 |  | ||||||
| namespace MoonTools.Core.Bonk |  | ||||||
| { |  | ||||||
|     public struct SimplexVertices : IEnumerable<Vector2> |  | ||||||
|     { |  | ||||||
|         public Vector2?[] vertices; |  | ||||||
| 
 |  | ||||||
|         /// <summary> |  | ||||||
|         /// Make sure to pass in all nulls |  | ||||||
|         /// </summary> |  | ||||||
|         public SimplexVertices(Vector2?[] vertices) |  | ||||||
|         { |  | ||||||
|             this.vertices = vertices; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         public Vector2 this[int key] |  | ||||||
|         { |  | ||||||
|             get |  | ||||||
|             { |  | ||||||
|                 if (!vertices[key].HasValue) { throw new IndexOutOfRangeException(); } |  | ||||||
|                 return vertices[key].Value; |  | ||||||
|             } |  | ||||||
|             set |  | ||||||
|             { |  | ||||||
|                 vertices[key] = value; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         public int Count { |  | ||||||
|             get |  | ||||||
|             { |  | ||||||
|                 for (int i = 0; i < vertices.Length; i++) |  | ||||||
|                 { |  | ||||||
|                     if (!vertices[i].HasValue) { return i; } |  | ||||||
|                 } |  | ||||||
|                 return vertices.Length; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         public void Add(Vector2 vertex) |  | ||||||
|         { |  | ||||||
|             if (Count > vertices.Length - 1) { throw new IndexOutOfRangeException(); } |  | ||||||
| 
 |  | ||||||
|             vertices[Count] = vertex; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         public void Insert(int index, Vector2 vertex) |  | ||||||
|         { |  | ||||||
|             if (Count >= vertices.Length || index > vertices.Length - 1) { throw new IndexOutOfRangeException(); } |  | ||||||
| 
 |  | ||||||
|             var currentCount = Count; |  | ||||||
| 
 |  | ||||||
|             for (int i = currentCount - 1; i >= index; i--) |  | ||||||
|             { |  | ||||||
|                 vertices[i + 1] = vertices[i]; |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             vertices[index] = vertex; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         public IEnumerator<Vector2> GetEnumerator() |  | ||||||
|         { |  | ||||||
|             foreach (Vector2? vec in vertices) |  | ||||||
|             { |  | ||||||
|                 if (!vec.HasValue) { yield break; } |  | ||||||
|                 yield return vec.Value; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         public void RemoveAt(int index) |  | ||||||
|         { |  | ||||||
|             if (index > vertices.Length - 1 || index > Count) { throw new ArgumentOutOfRangeException(); } |  | ||||||
| 
 |  | ||||||
|             for (int i = vertices.Length - 2; i >= index; i--) |  | ||||||
|             { |  | ||||||
|                 vertices[i] = vertices[i + 1]; |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             vertices[vertices.Length - 1] = null; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         IEnumerator IEnumerable.GetEnumerator() |  | ||||||
|         { |  | ||||||
|             return GetEnumerator(); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  | @ -1,4 +1,5 @@ | ||||||
| using System; | using System; | ||||||
|  | using System.Collections.Generic; | ||||||
| using Microsoft.Xna.Framework; | using Microsoft.Xna.Framework; | ||||||
| using MoonTools.Core.Structs; | using MoonTools.Core.Structs; | ||||||
| 
 | 
 | ||||||
|  | @ -6,17 +7,28 @@ namespace MoonTools.Core.Bonk | ||||||
| { | { | ||||||
|     public struct Line : IShape2D, IEquatable<IShape2D> |     public struct Line : IShape2D, IEquatable<IShape2D> | ||||||
|     { |     { | ||||||
|         private Position2D[] vertices; |         private Position2D v0; | ||||||
|  |         private Position2D v1; | ||||||
|  | 
 | ||||||
|  |         private IEnumerable<Position2D> vertices | ||||||
|  |         { | ||||||
|  |             get | ||||||
|  |             { | ||||||
|  |                 yield return v0; | ||||||
|  |                 yield return v0; | ||||||
|  |             } | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         public Line(Position2D start, Position2D end) |         public Line(Position2D start, Position2D end) | ||||||
|         { |         { | ||||||
|             vertices = new Position2D[2] { start, end }; |             v0 = start; | ||||||
|  |             v1 = end; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         public Vector2 Support(Vector2 direction, Transform2D transform) |         public Vector2 Support(Vector2 direction, Transform2D transform) | ||||||
|         { |         { | ||||||
|             var TransformedStart = Vector2.Transform(vertices[0], transform.TransformMatrix); |             var TransformedStart = Vector2.Transform(v0, transform.TransformMatrix); | ||||||
|             var TransformedEnd = Vector2.Transform(vertices[1], transform.TransformMatrix); |             var TransformedEnd = Vector2.Transform(v1, transform.TransformMatrix); | ||||||
|             return Vector2.Dot(TransformedStart, direction) > Vector2.Dot(TransformedEnd, direction) ? |             return Vector2.Dot(TransformedStart, direction) > Vector2.Dot(TransformedEnd, direction) ? | ||||||
|                 TransformedStart : |                 TransformedStart : | ||||||
|                 TransformedEnd; |                 TransformedEnd; | ||||||
|  | @ -32,7 +44,7 @@ namespace MoonTools.Core.Bonk | ||||||
|             if (other is Line) |             if (other is Line) | ||||||
|             { |             { | ||||||
|                 var otherLine = (Line)other; |                 var otherLine = (Line)other; | ||||||
|                 return vertices[0].ToVector2() == otherLine.vertices[0].ToVector2() && vertices[1].ToVector2() == otherLine.vertices[1].ToVector2(); |                 return v0.ToVector2() == otherLine.v0.ToVector2() && v1.ToVector2() == otherLine.v1.ToVector2(); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             return false; |             return false; | ||||||
|  |  | ||||||
|  | @ -1,6 +1,9 @@ | ||||||
| using System; | using System; | ||||||
|  | using System.Collections.Generic; | ||||||
|  | using System.Linq; | ||||||
| using Microsoft.Xna.Framework; | using Microsoft.Xna.Framework; | ||||||
| using MoonTools.Core.Structs; | using MoonTools.Core.Structs; | ||||||
|  | using MoreLinq; | ||||||
| 
 | 
 | ||||||
| namespace MoonTools.Core.Bonk | namespace MoonTools.Core.Bonk | ||||||
| { | { | ||||||
|  | @ -11,7 +14,16 @@ namespace MoonTools.Core.Bonk | ||||||
|         public int MaxX { get; } |         public int MaxX { get; } | ||||||
|         public int MaxY { get; } |         public int MaxY { get; } | ||||||
| 
 | 
 | ||||||
|         private Position2D[] vertices; |         private IEnumerable<Position2D> vertices | ||||||
|  |         { | ||||||
|  |             get | ||||||
|  |             { | ||||||
|  |                 yield return new Position2D(MinX, MinY); | ||||||
|  |                 yield return new Position2D(MinX, MaxY); | ||||||
|  |                 yield return new Position2D(MaxX, MinY); | ||||||
|  |                 yield return new Position2D(MaxX, MaxY); | ||||||
|  |             } | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         public Rectangle(int minX, int minY, int maxX, int maxY) |         public Rectangle(int minX, int minY, int maxX, int maxY) | ||||||
|         { |         { | ||||||
|  | @ -19,33 +31,11 @@ namespace MoonTools.Core.Bonk | ||||||
|             MinY = minY; |             MinY = minY; | ||||||
|             MaxX = maxX; |             MaxX = maxX; | ||||||
|             MaxY = maxY; |             MaxY = maxY; | ||||||
| 
 |  | ||||||
|             vertices = new Position2D[4] |  | ||||||
|             { |  | ||||||
|                 new Position2D(minX, minY), |  | ||||||
|                 new Position2D(minX, maxY), |  | ||||||
|                 new Position2D(maxX, minY), |  | ||||||
|                 new Position2D(maxX, maxY) |  | ||||||
|             }; |  | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         public Vector2 Support(Vector2 direction, Transform2D transform) |         public Vector2 Support(Vector2 direction, Transform2D transform) | ||||||
|         { |         { | ||||||
|             var furthestDistance = float.NegativeInfinity; |             return vertices.Select(vertex => Vector2.Transform(vertex, transform.TransformMatrix)).MaxBy(transformed => Vector2.Dot(transformed, direction)).First(); | ||||||
|             var furthestVertex = Vector2.Transform(vertices[0], transform.TransformMatrix); |  | ||||||
| 
 |  | ||||||
|             foreach (var v in vertices) |  | ||||||
|             { |  | ||||||
|                 var TransformedVertex = Vector2.Transform(v, transform.TransformMatrix); |  | ||||||
|                 var distance = Vector2.Dot(TransformedVertex, direction); |  | ||||||
|                 if (distance > furthestDistance) |  | ||||||
|                 { |  | ||||||
|                     furthestDistance = distance; |  | ||||||
|                     furthestVertex = TransformedVertex; |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             return furthestVertex; |  | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         public AABB AABB(Transform2D Transform2D) |         public AABB AABB(Transform2D Transform2D) | ||||||
|  |  | ||||||
|  | @ -0,0 +1,66 @@ | ||||||
|  | using System.Collections.Generic; | ||||||
|  | using Microsoft.Xna.Framework; | ||||||
|  | using MoonTools.Core.Structs; | ||||||
|  | using MoonTools.Core.Bonk.Extensions; | ||||||
|  | 
 | ||||||
|  | namespace MoonTools.Core.Bonk | ||||||
|  | { | ||||||
|  |     public struct Simplex : IShape2D | ||||||
|  |     { | ||||||
|  |         MinkowskiDifference minkowskiDifference; | ||||||
|  |         Vector2 directionA; | ||||||
|  |         Vector2 directionB; | ||||||
|  | 
 | ||||||
|  |         public Vector2 DirectionA { get { return directionA; } } | ||||||
|  |         public Vector2 DirectionB { get { return directionB; } } | ||||||
|  | 
 | ||||||
|  |         public Simplex(MinkowskiDifference minkowskiDifference, Vector2 directionA, Vector2 directionB) | ||||||
|  |         { | ||||||
|  |             this.minkowskiDifference = minkowskiDifference; | ||||||
|  |             this.directionA = directionA; | ||||||
|  |             this.directionB = directionB; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public Simplex WithDirections(Vector2 a, Vector2 b) | ||||||
|  |         { | ||||||
|  |             return new Simplex(minkowskiDifference, a, b); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public IEnumerable<Position2D> Vertices | ||||||
|  |         { | ||||||
|  |             get | ||||||
|  |             { | ||||||
|  |                 yield return (Position2D)Support(directionA); | ||||||
|  |                 yield return (Position2D)Support(directionB); | ||||||
|  |                 yield return (Position2D)Support(-(directionB - directionA).Perpendicular()); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public AABB AABB(Transform2D transform) | ||||||
|  |         { | ||||||
|  |             return Bonk.AABB.FromTransformedVertices(Vertices, transform); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public bool Equals(IShape2D other) | ||||||
|  |         { | ||||||
|  |             if (other is Simplex polytope) | ||||||
|  |             { | ||||||
|  |                 return minkowskiDifference.Equals(polytope.minkowskiDifference) && | ||||||
|  |                     directionA == polytope.directionA && | ||||||
|  |                     directionB == polytope.directionB; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public Vector2 Support(Vector2 direction) | ||||||
|  |         { | ||||||
|  |             return minkowskiDifference.Support(direction); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public Vector2 Support(Vector2 direction, Transform2D transform) | ||||||
|  |         { | ||||||
|  |             return Vector2.Transform(Support(direction), transform.TransformMatrix); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,18 @@ | ||||||
|  | using Microsoft.Xna.Framework; | ||||||
|  | 
 | ||||||
|  | namespace MoonTools.Core.Bonk.Extensions | ||||||
|  | { | ||||||
|  |     internal static class Vector2Extensions | ||||||
|  |     { | ||||||
|  |         internal static Vector2 Cross(this Vector2 a, Vector2 b) | ||||||
|  |         { | ||||||
|  |             var vec3 = Vector3.Cross(new Vector3(a.X, a.Y, 0), new Vector3(b.X, b.Y, 0)); | ||||||
|  |             return new Vector2(vec3.X, vec3.Y); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         internal static Vector2 Perpendicular(this Vector2 v) | ||||||
|  |         { | ||||||
|  |             return new Vector2(v.Y, -v.X); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -18,11 +18,11 @@ namespace Tests | ||||||
|             var squareB = new MoonTools.Core.Bonk.Rectangle(-1, -1, 1, 1); |             var squareB = new MoonTools.Core.Bonk.Rectangle(-1, -1, 1, 1); | ||||||
|             var transformB = new Transform2D(new Vector2(1.5f, 0)); |             var transformB = new Transform2D(new Vector2(1.5f, 0)); | ||||||
| 
 | 
 | ||||||
|             var test = GJK2D.TestCollision(squareA, transformA, squareB, transformB); |             var (result, simplex) = GJK2D.FindCollisionSimplex(squareA, transformA, squareB, transformB); | ||||||
| 
 | 
 | ||||||
|             Assert.That(test.Item1, Is.True); |             result.Should().BeTrue(); | ||||||
| 
 | 
 | ||||||
|             var intersection = EPA2D.Intersect(squareA, transformA, squareB, transformB, test.Item2); |             var intersection = EPA2D.Intersect(squareA, transformA, squareB, transformB, simplex); | ||||||
| 
 | 
 | ||||||
|             intersection.X.Should().Be(1f); |             intersection.X.Should().Be(1f); | ||||||
|             intersection.Y.Should().Be(0); |             intersection.Y.Should().Be(0); | ||||||
|  | @ -36,11 +36,11 @@ namespace Tests | ||||||
|             var circleB = new Circle(1); |             var circleB = new Circle(1); | ||||||
|             var transformB = new Transform2D(new Vector2(1, 1)); |             var transformB = new Transform2D(new Vector2(1, 1)); | ||||||
| 
 | 
 | ||||||
|             var test = GJK2D.TestCollision(circleA, transformA, circleB, transformB); |             var (result, simplex) = GJK2D.FindCollisionSimplex(circleA, transformA, circleB, transformB); | ||||||
| 
 | 
 | ||||||
|             Assert.That(test.Item1, Is.True); |             result.Should().BeTrue(); | ||||||
| 
 | 
 | ||||||
|             var intersection = EPA2D.Intersect(circleA, transformA, circleB, transformB, test.Item2); |             var intersection = EPA2D.Intersect(circleA, transformA, circleB, transformB, simplex); | ||||||
| 
 | 
 | ||||||
|             var ix = circleA.Radius * (float)Math.Cos(Math.PI / 4) - (circleB.Radius * (float)Math.Cos(5 * Math.PI / 4) + transformB.Position.X); |             var ix = circleA.Radius * (float)Math.Cos(Math.PI / 4) - (circleB.Radius * (float)Math.Cos(5 * Math.PI / 4) + transformB.Position.X); | ||||||
|             var iy = circleA.Radius * (float)Math.Sin(Math.PI / 4) - (circleB.Radius * (float)Math.Sin(5 * Math.PI / 4) + transformB.Position.Y); |             var iy = circleA.Radius * (float)Math.Sin(Math.PI / 4) - (circleB.Radius * (float)Math.Sin(5 * Math.PI / 4) + transformB.Position.Y); | ||||||
|  | @ -57,11 +57,11 @@ namespace Tests | ||||||
|             var square = new MoonTools.Core.Bonk.Rectangle(-1, -1, 1, 1); |             var square = new MoonTools.Core.Bonk.Rectangle(-1, -1, 1, 1); | ||||||
|             var transformB = Transform2D.DefaultTransform; |             var transformB = Transform2D.DefaultTransform; | ||||||
| 
 | 
 | ||||||
|             var test = GJK2D.TestCollision(line, transformA, square, transformB); |             var (result, simplex) = GJK2D.FindCollisionSimplex(line, transformA, square, transformB); | ||||||
| 
 | 
 | ||||||
|             Assert.That(test.Item1, Is.True); |             result.Should().BeTrue(); | ||||||
| 
 | 
 | ||||||
|             var intersection = EPA2D.Intersect(line, transformA, square, transformB, test.Item2); |             var intersection = EPA2D.Intersect(line, transformA, square, transformB, simplex); | ||||||
| 
 | 
 | ||||||
|             intersection.X.Should().Be(-1); |             intersection.X.Should().Be(-1); | ||||||
|             intersection.Y.Should().Be(1); |             intersection.Y.Should().Be(1); | ||||||
|  |  | ||||||
|  | @ -2,6 +2,7 @@ | ||||||
| using MoonTools.Core.Bonk; | using MoonTools.Core.Bonk; | ||||||
| using MoonTools.Core.Structs; | using MoonTools.Core.Structs; | ||||||
| using Microsoft.Xna.Framework; | using Microsoft.Xna.Framework; | ||||||
|  | using FluentAssertions; | ||||||
| 
 | 
 | ||||||
| namespace Tests | namespace Tests | ||||||
| { | { | ||||||
|  | @ -13,7 +14,7 @@ namespace Tests | ||||||
|             var lineA = new Line(new Position2D(-1, -1), new Position2D(1, 1)); |             var lineA = new Line(new Position2D(-1, -1), new Position2D(1, 1)); | ||||||
|             var lineB = new Line(new Position2D(-1, 1), new Position2D(1, -1)); |             var lineB = new Line(new Position2D(-1, 1), new Position2D(1, -1)); | ||||||
| 
 | 
 | ||||||
|             Assert.IsTrue(GJK2D.TestCollision(lineA, Transform2D.DefaultTransform, lineB, Transform2D.DefaultTransform).Item1); |             GJK2D.TestCollision(lineA, Transform2D.DefaultTransform, lineB, Transform2D.DefaultTransform).Should().BeTrue(); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         [Test] |         [Test] | ||||||
|  | @ -24,7 +25,7 @@ namespace Tests | ||||||
| 
 | 
 | ||||||
|             var transform = new Transform2D(new Position2D(0, 0), 0f, new Vector2(2, 2)); |             var transform = new Transform2D(new Position2D(0, 0), 0f, new Vector2(2, 2)); | ||||||
| 
 | 
 | ||||||
|             Assert.IsTrue(GJK2D.TestCollision(lineA, transform, lineB, transform).Item1); |             GJK2D.TestCollision(lineA, transform, lineB, transform).Should().BeTrue(); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         [Test] |         [Test] | ||||||
|  | @ -33,7 +34,7 @@ namespace Tests | ||||||
|             var lineA = new Line(new Position2D(0, 1), new Position2D(1, 0)); |             var lineA = new Line(new Position2D(0, 1), new Position2D(1, 0)); | ||||||
|             var lineB = new Line(new Position2D(-1, -1), new Position2D(-2, -2)); |             var lineB = new Line(new Position2D(-1, -1), new Position2D(-2, -2)); | ||||||
| 
 | 
 | ||||||
|             Assert.IsFalse(GJK2D.TestCollision(lineA, Transform2D.DefaultTransform, lineB, Transform2D.DefaultTransform).Item1); |             GJK2D.TestCollision(lineA, Transform2D.DefaultTransform, lineB, Transform2D.DefaultTransform).Should().BeFalse(); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         [Test] |         [Test] | ||||||
|  | @ -44,7 +45,7 @@ namespace Tests | ||||||
| 
 | 
 | ||||||
|             var transform = new Transform2D(new Position2D(0, 0), 0f, new Vector2(2, 2)); |             var transform = new Transform2D(new Position2D(0, 0), 0f, new Vector2(2, 2)); | ||||||
| 
 | 
 | ||||||
|             Assert.IsFalse(GJK2D.TestCollision(lineA, transform, lineB, transform).Item1); |             GJK2D.TestCollision(lineA, transform, lineB, transform).Should().BeFalse(); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         [Test] |         [Test] | ||||||
|  | @ -55,7 +56,7 @@ namespace Tests | ||||||
|             var circleB = new Circle(2); |             var circleB = new Circle(2); | ||||||
|             var transformB = new Transform2D(new Vector2(1, 1)); |             var transformB = new Transform2D(new Vector2(1, 1)); | ||||||
| 
 | 
 | ||||||
|             Assert.IsTrue(GJK2D.TestCollision(circleA, transformA, circleB, transformB).Item1); |             GJK2D.TestCollision(circleA, transformA, circleB, transformB).Should().BeTrue(); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         [Test] |         [Test] | ||||||
|  | @ -66,7 +67,7 @@ namespace Tests | ||||||
|             var circleB = new Circle(2); |             var circleB = new Circle(2); | ||||||
|             var transformB = new Transform2D(new Vector2(3, 0), 0f, new Vector2(2, 2)); |             var transformB = new Transform2D(new Vector2(3, 0), 0f, new Vector2(2, 2)); | ||||||
| 
 | 
 | ||||||
|             Assert.IsTrue(GJK2D.TestCollision(circleA, transformA, circleB, transformB).Item1); |             GJK2D.TestCollision(circleA, transformA, circleB, transformB).Should().BeTrue(); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         [Test] |         [Test] | ||||||
|  | @ -77,7 +78,7 @@ namespace Tests | ||||||
|             var circleB = new Circle(2); |             var circleB = new Circle(2); | ||||||
|             var transformB = new Transform2D(new Vector2(5, 5)); |             var transformB = new Transform2D(new Vector2(5, 5)); | ||||||
| 
 | 
 | ||||||
|             Assert.IsFalse(GJK2D.TestCollision(circleA, transformA, circleB, transformB).Item1); |             GJK2D.TestCollision(circleA, transformA, circleB, transformB).Should().BeFalse(); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         [Test] |         [Test] | ||||||
|  | @ -88,7 +89,7 @@ namespace Tests | ||||||
|             var circleB = new Circle(2); |             var circleB = new Circle(2); | ||||||
|             var transformB = new Transform2D(new Vector2(5, 5), 0, new Vector2(0.2f, 0.2f)); |             var transformB = new Transform2D(new Vector2(5, 5), 0, new Vector2(0.2f, 0.2f)); | ||||||
| 
 | 
 | ||||||
|             Assert.IsFalse(GJK2D.TestCollision(circleA, transformA, circleB, transformB).Item1); |             GJK2D.TestCollision(circleA, transformA, circleB, transformB).Should().BeFalse(); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         [Test] |         [Test] | ||||||
|  | @ -108,7 +109,7 @@ namespace Tests | ||||||
| 
 | 
 | ||||||
|             var transformB = new Transform2D(new Vector2(0.5f, 0.5f)); |             var transformB = new Transform2D(new Vector2(0.5f, 0.5f)); | ||||||
| 
 | 
 | ||||||
|             Assert.IsTrue(GJK2D.TestCollision(shapeA, transformA, shapeB, transformB).Item1); |             GJK2D.TestCollision(shapeA, transformA, shapeB, transformB).Should().BeTrue(); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         [Test] |         [Test] | ||||||
|  | @ -128,7 +129,7 @@ namespace Tests | ||||||
| 
 | 
 | ||||||
|             var transformB = new Transform2D(new Vector2(3f, 0f), 0f, new Vector2(3f, 3f)); |             var transformB = new Transform2D(new Vector2(3f, 0f), 0f, new Vector2(3f, 3f)); | ||||||
| 
 | 
 | ||||||
|             Assert.IsTrue(GJK2D.TestCollision(shapeA, transformA, shapeB, transformB).Item1); |             GJK2D.TestCollision(shapeA, transformA, shapeB, transformB).Should().BeTrue(); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         [Test] |         [Test] | ||||||
|  | @ -148,7 +149,7 @@ namespace Tests | ||||||
| 
 | 
 | ||||||
|             var transformB = new Transform2D(new Vector2(5, 0)); |             var transformB = new Transform2D(new Vector2(5, 0)); | ||||||
| 
 | 
 | ||||||
|             Assert.IsFalse(GJK2D.TestCollision(shapeA, transformA, shapeB, transformB).Item1); |             GJK2D.TestCollision(shapeA, transformA, shapeB, transformB).Should().BeFalse(); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         [Test] |         [Test] | ||||||
|  | @ -162,13 +163,13 @@ namespace Tests | ||||||
|             var transformA = Transform2D.DefaultTransform; |             var transformA = Transform2D.DefaultTransform; | ||||||
| 
 | 
 | ||||||
|             var shapeB = new Polygon( |             var shapeB = new Polygon( | ||||||
|                 new Position2D(-1, 1), new Position2D(1, 1), |                 new Position2D(-2, 2), new Position2D(2, 2), | ||||||
|                 new Position2D(-1, -1), new Position2D(1, -1) |                 new Position2D(-2, -2), new Position2D(2, -2) | ||||||
|             ); |             ); | ||||||
| 
 | 
 | ||||||
|             var transformB = new Transform2D(new Vector2(2f, 0), 0f, new Vector2(0.2f, 0.2f)); |             var transformB = new Transform2D(new Vector2(3f, 0), 0f, new Vector2(0.5f, 0.5f)); | ||||||
| 
 | 
 | ||||||
|             Assert.IsFalse(GJK2D.TestCollision(shapeA, transformA, shapeB, transformB).Item1);   |             GJK2D.TestCollision(shapeA, transformA, shapeB, transformB).Should().BeFalse(); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         [Test] |         [Test] | ||||||
|  | @ -185,7 +186,7 @@ namespace Tests | ||||||
| 
 | 
 | ||||||
|             var transformB = Transform2D.DefaultTransform; |             var transformB = Transform2D.DefaultTransform; | ||||||
| 
 | 
 | ||||||
|             Assert.IsTrue(GJK2D.TestCollision(line, transformA, polygon, transformB).Item1); |             GJK2D.TestCollision(line, transformA, polygon, transformB).Should().BeTrue(); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         [Test] |         [Test] | ||||||
|  | @ -202,7 +203,7 @@ namespace Tests | ||||||
| 
 | 
 | ||||||
|             var transformB = Transform2D.DefaultTransform; |             var transformB = Transform2D.DefaultTransform; | ||||||
| 
 | 
 | ||||||
|             Assert.IsFalse(GJK2D.TestCollision(line, transformA, polygon, transformB).Item1); |             GJK2D.TestCollision(line, transformA, polygon, transformB).Should().BeFalse(); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         [Test] |         [Test] | ||||||
|  | @ -213,7 +214,7 @@ namespace Tests | ||||||
|             var circle = new Circle(1); |             var circle = new Circle(1); | ||||||
|             var transformB = Transform2D.DefaultTransform; |             var transformB = Transform2D.DefaultTransform; | ||||||
| 
 | 
 | ||||||
|             Assert.IsTrue(GJK2D.TestCollision(line, transformA, circle, transformB).Item1); |             GJK2D.TestCollision(line, transformA, circle, transformB).Should().BeTrue(); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         [Test] |         [Test] | ||||||
|  | @ -224,7 +225,7 @@ namespace Tests | ||||||
|             var circle = new Circle(1); |             var circle = new Circle(1); | ||||||
|             var transformB = Transform2D.DefaultTransform; |             var transformB = Transform2D.DefaultTransform; | ||||||
| 
 | 
 | ||||||
|             Assert.IsFalse(GJK2D.TestCollision(line, transformA, circle, transformB).Item1); |             GJK2D.TestCollision(line, transformA, circle, transformB).Should().BeFalse(); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         [Test] |         [Test] | ||||||
|  | @ -240,7 +241,7 @@ namespace Tests | ||||||
| 
 | 
 | ||||||
|             var transformB = Transform2D.DefaultTransform; |             var transformB = Transform2D.DefaultTransform; | ||||||
| 
 | 
 | ||||||
|             Assert.IsTrue(GJK2D.TestCollision(circle, transformA, square, transformB).Item1); |             GJK2D.TestCollision(circle, transformA, square, transformB).Should().BeTrue(); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         [Test] |         [Test] | ||||||
|  | @ -255,7 +256,7 @@ namespace Tests | ||||||
|             ); |             ); | ||||||
|             var squareTransform = Transform2D.DefaultTransform; |             var squareTransform = Transform2D.DefaultTransform; | ||||||
| 
 | 
 | ||||||
|             Assert.IsFalse(GJK2D.TestCollision(circle, circleTransform, square, squareTransform).Item1); |             GJK2D.TestCollision(circle, circleTransform, square, squareTransform).Should().BeFalse(); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         [Test] |         [Test] | ||||||
|  | @ -267,7 +268,7 @@ namespace Tests | ||||||
|             var rectangleB = new MoonTools.Core.Bonk.Rectangle(-1, -1, 1, 1); |             var rectangleB = new MoonTools.Core.Bonk.Rectangle(-1, -1, 1, 1); | ||||||
|             var transformB = new Transform2D(new Vector2(1, 0)); |             var transformB = new Transform2D(new Vector2(1, 0)); | ||||||
| 
 | 
 | ||||||
|             Assert.IsTrue(GJK2D.TestCollision(rectangleA, transformA, rectangleB, transformB).Item1); |             GJK2D.TestCollision(rectangleA, transformA, rectangleB, transformB).Should().BeTrue(); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         [Test] |         [Test] | ||||||
|  | @ -279,7 +280,7 @@ namespace Tests | ||||||
|             var rectangleB = new MoonTools.Core.Bonk.Rectangle(-1, -1, 1, 1); |             var rectangleB = new MoonTools.Core.Bonk.Rectangle(-1, -1, 1, 1); | ||||||
|             var transformB = new Transform2D(new Vector2(1, 0)); |             var transformB = new Transform2D(new Vector2(1, 0)); | ||||||
| 
 | 
 | ||||||
|             Assert.IsTrue(GJK2D.TestCollision(rectangleA, transformA, rectangleB, transformB).Item1); |             GJK2D.TestCollision(rectangleA, transformA, rectangleB, transformB).Should().BeTrue(); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1,6 +1,6 @@ | ||||||
| <Project Sdk="Microsoft.NET.Sdk"> | <Project Sdk="Microsoft.NET.Sdk"> | ||||||
|   <PropertyGroup> |   <PropertyGroup> | ||||||
|     <TargetFramework>netcoreapp2.2</TargetFramework> |     <TargetFramework>netcoreapp3.0</TargetFramework> | ||||||
|     <IsPackable>false</IsPackable> |     <IsPackable>false</IsPackable> | ||||||
|   </PropertyGroup> |   </PropertyGroup> | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue