private bool CheckPolygonGrid(IShape A, Vector2 APos, IShape B, Vector2 BPos, out Contact[] contacts) { PolygonShape polygonShapeA = A as PolygonShape; GridShape gridB = B as GridShape; Rectangle polygonBoundingBox = polygonShapeA.BoundingBox + APos, gridBoundingBox = gridB.BoundingBox + BPos; // test grid bounds if (!gridBoundingBox.Intersects(polygonBoundingBox)) { contacts = null; return(false); } Polygon polygonA = new Polygon(polygonShapeA.Shape); polygonA.Translate(APos); List <Contact> gridContacts = TestGrid(gridB, BPos, polygonBoundingBox, (Polygon tilePolygon) => { SAT.Test(polygonA, tilePolygon, out Contact? tileContact); return(tileContact); } ); if (gridContacts.Count > 0) { contacts = gridContacts.ToArray(); return(true); } contacts = null; return(false); }
private List <Contact> TestGrid(GridShape grid, Vector2 gridPos, Rectangle otherBoundingBox, System.Func <Polygon, Contact?> SAT) { List <Contact> contacts = new List <Contact>(); Polygon boxTilePolygon = new Polygon(grid.BoxTilePolygon); boxTilePolygon.Translate(gridPos); (int column, int row)start = grid.ConvertPosition(gridPos, otherBoundingBox.TopLeft - Vector2.One), end = grid.ConvertPosition(gridPos, otherBoundingBox.BottomRight + Vector2.One); List <Polygon> tilePolygons = new List <Polygon>(); foreach ((int Column, int Row, GridShape.TileShape Shape)tile in grid.Tiles(start, end)) { tilePolygons.Clear(); if (tile.Shape != null) { if (tile.Shape is GridShape.BoxTileShape boxShape) { tilePolygons.Add(boxShape.CreateCollisionPolygon(grid, gridPos, tile.Column, tile.Row)); } else if (tile.Shape is GridShape.PolygonTileShape polygonShape) { tilePolygons.AddRange(polygonShape.CreateCollisionPolygons(grid, gridPos, tile.Column, tile.Row)); } else { throw new System.InvalidOperationException($"Unable to find shape '{tile.Shape.GetType().Name}'."); } } Location cell = new Location(tile.Column, tile.Row); foreach (Polygon tilePolygon in tilePolygons) { Contact?contact = SAT(tilePolygon); if (contact == null) { continue; } contacts.Add(new Contact(contact.Value.Position, contact.Value.Normal, contact.Value.PenetrationDepth, cell)); } } return(contacts); }
private bool CheckCircleGrid(IShape A, Vector2 APos, IShape B, Vector2 BPos, out Contact[] contacts) { CircleShape circleA = A as CircleShape; GridShape gridB = B as GridShape; // test grid bounds Vector2 closestPoint = new Rectangle(BPos, gridB.Size).ClosestPoint(APos); Vector2 diff = closestPoint - APos; if (Vector2.Dot(diff, diff) > circleA.Radius * circleA.Radius) { contacts = null; return(false); } List <Contact> gridContacts = TestGrid(gridB, BPos, new Rectangle(APos - circleA.Radius, APos + circleA.Radius), (Polygon tilePolygon) => { SAT.Test(circleA, APos, tilePolygon, out Contact? tileContact); if (tileContact == null) { return(null); } return(new Contact(closestPoint, tileContact.Value.Normal, tileContact.Value.PenetrationDepth, null)); } ); if (gridContacts.Count > 0) { contacts = gridContacts.ToArray(); return(true); } contacts = null; return(false); }