/// <summary> /// Returns whether this instance collides with the argument AxisAlignedRectangle. /// </summary> /// <param name="rectangle">The AxisAlignedRectangle to test collision against.</param> /// <returns>Whether a collision has occurred.</returns> #endregion public bool CollideAgainst(AxisAlignedRectangle rectangle) { UpdateDependencies(TimeManager.CurrentTime); rectangle.UpdateDependencies(TimeManager.CurrentTime); // Get world-positioned segment Segment a = AsSegment(); // Check if one of the segment's endpoints is inside the rectangle Vector3 endpoint = new Vector3( (float)a.Point1.X, (float)a.Point1.Y, 0f); if (rectangle.IsPointInside(ref endpoint)) { mLastCollisionPoint = new Point(ref endpoint); return(true); } endpoint = new Vector3( (float)a.Point2.X, (float)a.Point2.Y, 0f); if (rectangle.IsPointInside(ref endpoint)) { mLastCollisionPoint = new Point(ref endpoint); return(true); } // Check if the segment intersects any of the rectangle's edges // Here, prepare rectangle's corner points Point tl = new Point( rectangle.Position.X - rectangle.ScaleX, rectangle.Position.Y + rectangle.ScaleY); Point tr = new Point( rectangle.Position.X + rectangle.ScaleX, rectangle.Position.Y + rectangle.ScaleY); Point bl = new Point( rectangle.Position.X - rectangle.ScaleX, rectangle.Position.Y - rectangle.ScaleY); Point br = new Point( rectangle.Position.X + rectangle.ScaleX, rectangle.Position.Y - rectangle.ScaleY); Point tempPoint; // Test if any of the edges intersect the segment // (this will short-circuit on the first true test) if (a.Intersects(new Segment(tl, tr), out tempPoint) || a.Intersects(new Segment(tl, bl), out tempPoint) || a.Intersects(new Segment(bl, br), out tempPoint) || a.Intersects(new Segment(tr, br), out tempPoint)) { mLastCollisionPoint = tempPoint; return(true); } // No collision return(false); }
public bool CollideAgainst(AxisAlignedRectangle rectangle) { if (mLastDependencyUpdate != TimeManager.CurrentTime) { UpdateDependencies(TimeManager.CurrentTime); } if (rectangle.LastDependencyUpdate != TimeManager.CurrentTime) { rectangle.UpdateDependencies(TimeManager.CurrentTime); } // first perform a quick test to see if the Circle is too far // away from the rectangle if ((Position.X + Radius < rectangle.X - rectangle.mScaleX || Position.X - Radius > rectangle.X + rectangle.mScaleX || Position.Y + Radius < rectangle.Y - rectangle.mScaleY || Position.Y - Radius > rectangle.Y + rectangle.mScaleY)) { return(false); } // The simple bounding box test from above will eliminate most // cases. If we get this far, then it is likely that we have a collision // and a more in-depth test can be performed. // quick test to see if the circle is inside of the rectangle if (rectangle.IsPointInside(Position.X, Position.Y)) { mLastCollisionTangent.X = -(Position.Y - rectangle.Position.Y); mLastCollisionTangent.Y = (Position.X - rectangle.Position.X); return(true); } // if we got this far, the bounding box of the circle touches the rectangle // and the center of the circle is not inside of the rectangle. Perform // the most expensive checks now. Point centerPoint = new Point(Position.X, Position.Y); Segment connectingSegment = new Segment(); int numberOfEndpointsClosestTo = 0; // top segment Segment segment = new Segment( new Point(rectangle.Left, rectangle.Top), new Point(rectangle.Right, rectangle.Top)); if (segment.DistanceTo(centerPoint, out connectingSegment) < Radius) { if (segment.IsClosestPointOnEndpoint(ref centerPoint)) { mLastCollisionTangent.X = -(connectingSegment.Point2.Y - Y); mLastCollisionTangent.Y = (connectingSegment.Point2.X - X); numberOfEndpointsClosestTo++; } else { mLastCollisionTangent.X = 1; mLastCollisionTangent.Y = 0; return(true); } } // bottom segment segment = new Segment( new Point(rectangle.Left, rectangle.Bottom), new Point(rectangle.Right, rectangle.Bottom)); if (segment.DistanceTo(centerPoint, out connectingSegment) < Radius) { if (segment.IsClosestPointOnEndpoint(ref centerPoint)) { mLastCollisionTangent.X = -(connectingSegment.Point2.Y - Position.Y); mLastCollisionTangent.Y = (connectingSegment.Point2.X - Position.X); numberOfEndpointsClosestTo++; } else { mLastCollisionTangent.X = 1; mLastCollisionTangent.Y = 0; return(true); } } // left segment segment = new Segment( new Point(rectangle.Left, rectangle.Top), new Point(rectangle.Left, rectangle.Bottom)); if (segment.DistanceTo(centerPoint, out connectingSegment) < Radius) { if (segment.IsClosestPointOnEndpoint(ref centerPoint)) { mLastCollisionTangent.X = -(connectingSegment.Point2.Y - Position.Y); mLastCollisionTangent.Y = (connectingSegment.Point2.X - Position.X); numberOfEndpointsClosestTo++; } else { mLastCollisionTangent.X = 0; mLastCollisionTangent.Y = 1; return(true); } } // right segment segment = new Segment( new Point(rectangle.Right, rectangle.Top), new Point(rectangle.Right, rectangle.Bottom)); if (segment.DistanceTo(centerPoint, out connectingSegment) < Radius) { if (segment.IsClosestPointOnEndpoint(ref centerPoint)) { mLastCollisionTangent.X = -(connectingSegment.Point2.Y - Position.Y); mLastCollisionTangent.Y = (connectingSegment.Point2.X - Position.X); numberOfEndpointsClosestTo++; } else { mLastCollisionTangent.X = 0; mLastCollisionTangent.Y = 1; return(true); } } if (numberOfEndpointsClosestTo > 0) { return(true); } else // well, this is rare, but it can happen. Collision failed! { return(false); } }