8
\$\begingroup\$

I have a Breakout game in which, at some point, I detect the collision between the ball and the paddle with something like this:

// Ball class
rectangle.Intersects(paddle.Rectangle);

Is there any way I can get the exact coordinates of the collision, or any details about it, with the current XNA API?

I thought of doing some basic calculations, such as comparing the exact coordinates of each object on the moment of the collision. It would look something like this:

// Ball class
if((rectangle.X - paddle.Rectangle.X) < (paddle.Rectangle.Width / 2))
    // Collision happened on the left side
else
    // Collision happened on the right side

But I'm not sure this is the correct way to do it.

Do you guys have any tips on maybe an engine I might have to use to achieve that? Or even good coding practices using this method?

\$\endgroup\$

2 Answers 2

7
\$\begingroup\$

XNA's rectangles are pretty limited. The Rectangle.Intersects() method only returns a boolean result, so you'll need to do more tests yourself if you want details. You can, however, use the Rectangle.Intersect(Rectangle, Rectangle) method to get the rectangle where the two overlap. That will give you some information on depth and location, at least.

\$\endgroup\$
5
  • \$\begingroup\$ Is this get the rectangle where the two overlap functionallity available on the XNA API or I have to download some extra stuff, like the Platformer Starter Kit? \$\endgroup\$ Dec 19, 2012 at 12:20
  • 1
    \$\begingroup\$ Which method is this? I don't recall that XNA 4.0 supports Rectangle Rectangle.Intersects(...). \$\endgroup\$
    – ashes999
    Dec 19, 2012 at 12:25
  • \$\begingroup\$ Someone gave me the right at stackoverflow: msdn.microsoft.com/en-us/library/… \$\endgroup\$ Dec 19, 2012 at 12:55
  • \$\begingroup\$ Ok, with the returned Rectangle, how can I check the position of the paddle that got collided by the ball? \$\endgroup\$ Dec 19, 2012 at 21:59
  • \$\begingroup\$ If you know that the paddle and ball are intersecting then you use the location information of the paddle rectangle that you checked in the first place, i.e. rectangle.X or rectangle.Y or whatever you want to access. \$\endgroup\$
    – ssb
    Dec 20, 2012 at 0:00
4
\$\begingroup\$

Update: If you're using MonoGame, then as of 3.0 beta, Rectangle Rectangle.Intersect(rectangle, rectangle) doesn't exist. You can use the below code from the XNA Platformer kit instead.


You can download the XNA Platformer Starter Kit (ported to Windows 7). It ships with a helper extension method that returns a rectangle describing the intersection of two rectangles:

static class RectangleExtensions
    {
        /// <summary>
        /// Calculates the signed depth of intersection between two rectangles.
        /// </summary>
        /// <returns>
        /// The amount of overlap between two intersecting rectangles. These
        /// depth values can be negative depending on which wides the rectangles
        /// intersect. This allows callers to determine the correct direction
        /// to push objects in order to resolve collisions.
        /// If the rectangles are not intersecting, Vector2.Zero is returned.
        /// </returns>
        public static Vector2 GetIntersectionDepth(this Rectangle rectA, Rectangle rectB)
        {
            // Calculate half sizes.
            float halfWidthA = rectA.Width / 2.0f;
            float halfHeightA = rectA.Height / 2.0f;
            float halfWidthB = rectB.Width / 2.0f;
            float halfHeightB = rectB.Height / 2.0f;

            // Calculate centers.
            Vector2 centerA = new Vector2(rectA.Left + halfWidthA, rectA.Top + halfHeightA);
            Vector2 centerB = new Vector2(rectB.Left + halfWidthB, rectB.Top + halfHeightB);

            // Calculate current and minimum-non-intersecting distances between centers.
            float distanceX = centerA.X - centerB.X;
            float distanceY = centerA.Y - centerB.Y;
            float minDistanceX = halfWidthA + halfWidthB;
            float minDistanceY = halfHeightA + halfHeightB;

            // If we are not intersecting at all, return (0, 0).
            if (Math.Abs(distanceX) >= minDistanceX || Math.Abs(distanceY) >= minDistanceY)
                return Vector2.Zero;

            // Calculate and return intersection depths.
            float depthX = distanceX > 0 ? minDistanceX - distanceX : -minDistanceX - distanceX;
            float depthY = distanceY > 0 ? minDistanceY - distanceY : -minDistanceY - distanceY;
            return new Vector2(depthX, depthY);
        }

        /// <summary>
        /// Gets the position of the center of the bottom edge of the rectangle.
        /// </summary>
        public static Vector2 GetBottomCenter(this Rectangle rect)
        {
            return new Vector2(rect.X + rect.Width / 2.0f, rect.Bottom);
        }
}
\$\endgroup\$
10
  • \$\begingroup\$ Thank you very much for this link. May I ask you why did you need to use a modified version? Is that port official? \$\endgroup\$ Dec 19, 2012 at 12:21
  • \$\begingroup\$ @DanielRibeiro I checked my history and apparently I didn't modify it after all. The port is unofficial; I simply couldn't find the original. It works with MonoGame/C#, which was good enough for me. \$\endgroup\$
    – ashes999
    Dec 19, 2012 at 12:24
  • \$\begingroup\$ But there is an original port, right? Isn't this supposed to be such a simple feature? Anyways, I'm not using MonoGame, just XNA. Would you still recommend me to use this port? \$\endgroup\$ Dec 19, 2012 at 12:27
  • \$\begingroup\$ I had to set the correct answer to ssb, but thank you very much for this. I'll for sure get into this port! Many thanks! \$\endgroup\$ Dec 19, 2012 at 12:56
  • 1
    \$\begingroup\$ @DanielRibeiro ah, I see. I think that method doesn't exist in MonoGame, which is why I ended up using this approach. Cheers though. \$\endgroup\$
    – ashes999
    Dec 19, 2012 at 14:27

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .