private static Boolean CircCirc(CollisionCircle comp1, CollisionCircle comp2) { double rad1 = comp1.Radius; double rad2 = comp2.Radius; double rad1Squared = rad1 * rad1; double rad2Squared = rad2 * rad2; double distanceSquared = (comp1.Center - comp2.Center).LengthSquared; if (distanceSquared >= rad1Squared + rad2Squared) { return false; } return true; }
private static Boolean RectCirc(CollisionRectangle rectangle, CollisionCircle circle) { // Transform rectangle corner coordinates and circle center to be axis-aligned Matrix rotationMatrix = new Matrix(); rotationMatrix.Set2DRotate(-1 * rectangle.Rotation); Vector rotatedTopLeft = rectangle.TopLeft * rotationMatrix; Vector rotatedTopRight = rectangle.TopRight * rotationMatrix; Vector rotatedBottomLeft = rectangle.BottomLeft * rotationMatrix; Vector rotatedBottomRight = rectangle.BottomRight * rotationMatrix; Vector rotatedCircleCenter = circle.Center * rotationMatrix; double circRadius = circle.Radius; Vector rotatedRectangleCenter = rotatedTopLeft + (rotatedBottomRight - rotatedTopLeft).Multiply(0.5); double rectPercent = rectangle.CollisionPercent; // Use of doubles and matrix operations can cause very very small discrepencies that should be ignored if (Math.Abs(rotatedTopLeft.Y - rotatedTopRight.Y) > 0.00000001) { throw new Exception("Coordinate transform failed in CollisionDetector.RectCirc. TopLeft is " + rotatedTopLeft + " and TopRight is "+ rotatedTopRight); } bool isCircCenterOutsideRect = true; double rectHalfWidth = 0.5 * Math.Abs(rotatedTopRight.X - rotatedTopLeft.X) * rectPercent; double halfWidthPlusRadius = rectHalfWidth + circRadius; double xSeparation = Math.Abs(rotatedCircleCenter.X - rotatedRectangleCenter.X); if (xSeparation >= halfWidthPlusRadius) { return false; } if (xSeparation < rectHalfWidth) { isCircCenterOutsideRect = false; } double rectHalfHeight = 0.5 * Math.Abs(rotatedTopRight.Y - rotatedBottomRight.Y) * rectPercent; double halfHeightPlusRadius = rectHalfWidth + circRadius; double ySeparation = Math.Abs(rotatedCircleCenter.Y - rotatedRectangleCenter.Y); if (ySeparation >= halfHeightPlusRadius) { return false; } if (ySeparation < rectHalfHeight) { isCircCenterOutsideRect = false; } if (!isCircCenterOutsideRect) { return true; } // Check for literal corner cases Vector closestCorner; if (rotatedCircleCenter.X > rotatedRectangleCenter.X && rotatedCircleCenter.Y > rotatedRectangleCenter.Y) { closestCorner = rotatedTopRight; } else if (rotatedCircleCenter.X > rotatedRectangleCenter.X && rotatedCircleCenter.Y <= rotatedRectangleCenter.Y) { closestCorner = rotatedBottomRight; } else if (rotatedCircleCenter.Y > rotatedRectangleCenter.Y) { closestCorner = rotatedTopLeft; } else { closestCorner = rotatedBottomLeft; } if ((closestCorner - rotatedCircleCenter).LengthSquared > circRadius * circRadius) { return false; } return true; }