예제 #1
0
        /// <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);
        }
예제 #2
0
        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);
            }
        }