public void UpdateCollisions() { foreach (var b in bodies) { //destroy objects outside of bounds if ((b.position.X < -boundarySize || b.position.X > sceneWidth + boundarySize || b.position.Y < -boundarySize || b.position.Y > sceneHeight + boundarySize) && b.owner is Placeholder == false) { b.owner.health = 0; } } //clean grid for (int x = 0; x < gridSize; x++) { for (int y = 0; y < gridSize; y++) { colliderGrid[x][y].Clear(); } } //place objects into 2D grid foreach (var body in bodies) { int tileX = Mathfp.Floor(body.position.X / gridCellWidth); int tileY = Mathfp.Floor(body.position.Y / gridCellHeight); body.occupiedTile = new Point(tileX, tileY); //inject into grid, including adjacent tiles for (int x = tileX - 1; x <= tileX + 1; x++) { for (int y = tileY - 1; y <= tileY + 1; y++) { if (x >= 0 && x < gridSize && y >= 0 && y < gridSize) { colliderGrid[x][y].PutIntoFreeSlot(body); } } } } //check collisions for (int i = 0; i < contactCapacity; i++) { contacts[i].confirmed = false; } foreach (var body in bodies) { int x = body.occupiedTile.x; int y = body.occupiedTile.y; //ignore objects outside grid if (!(x >= 0 && x < gridSize && y > 0 && y < gridSize)) { continue; } foreach (var other in colliderGrid[x][y]) { if (other != null && other != body) { if (body.CanCollideWith(other) && PerformCollision(body, other)) { int existing = FindExistingContact(body, other); if (existing == -1) { var contact = new Connection(body, other); if (AddContact(contact)) { behaviorController.SendCollisionEnter(contact); } } else { behaviorController.SendCollisionContinue(contacts[existing]); contacts[existing].confirmed = true; } } } } } for (int i = 0; i < contactCapacity; i++) { if (contacts[i].alive && contacts[i].confirmed == false) { behaviorController.SendCollisionExit(contacts[i]); contacts[i].alive = false; } } }