Получить сведения о столкновении из Rectangle.Intersects ()

9

У меня есть игра Breakout, в которой в какой-то момент я обнаруживаю столкновение между мячом и веслом примерно так:

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

Есть ли способ, которым я могу получить точные координаты столкновения или какие-либо подробности о нем, с текущим XNA API?

Я подумал о некоторых базовых вычислениях, таких как сравнение точных координат каждого объекта в момент столкновения. Это будет выглядеть примерно так:

// 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

Но я не уверен, что это правильный способ сделать это.

У вас есть какие-нибудь советы по поводу двигателя, который мне, возможно, придется использовать для достижения этой цели? Или даже хорошие практики кодирования с использованием этого метода?

Даниэль Рибейро
источник

Ответы:

8

Прямоугольники XNA довольно ограничены. Rectangle.Intersects()Метод возвращает только логический результат, так что вам нужно сделать больше тестов себя , если вы хотите подробностей. Вы можете, однако, использовать Rectangle.Intersect(Rectangle, Rectangle)метод, чтобы получить прямоугольник, где эти два перекрываются. Это даст вам некоторую информацию о глубине и местоположении, по крайней мере.

ОБП
источник
get the rectangle where the two overlapДоступна ли эта функция на XNA APIили мне нужно загрузить некоторые дополнительные материалы, например Platformer Starter Kit?
Даниэль Рибейро
1
Какой это метод? Я не помню, чтобы XNA 4.0 поддерживала Rectangle Rectangle.Intersects(...).
ashes999
Кто-то дал мне право на работу со стеком
Даниэль Рибейро
Хорошо, с возвращенным прямоугольником, как я могу проверить положение весла, столкнувшегося с мячом?
Даниэль Рибейро
Если вы знаете, что весло и мяч пересекаются, то вы используете информацию о местоположении прямоугольника весла, который вы отметили в первую очередь, т. rectangle.XЕ. rectangle.YИли что-либо еще, к чему вы хотите получить доступ.
Ссб
4

Обновление: если вы используете MonoGame, то, начиная с бета-версии 3.0, Rectangle Rectangle.Intersect(rectangle, rectangle)не существует. Вместо этого вы можете использовать приведенный ниже код из набора XNA Platformer.


Вы можете скачать XNA Platformer Starter Kit ( портирован на Windows 7 ). Он поставляется с вспомогательным методом расширения, который возвращает прямоугольник, описывающий пересечение двух прямоугольников:

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);
        }
}
ashes999
источник
Большое спасибо за эту ссылку. Могу я спросить, зачем вам понадобилась модифицированная версия? Это официальный порт?
Даниэль Рибейро
@DanielRibeiro Я проверил свою историю и, видимо, я не изменил ее в конце концов. Порт неофициальный; Я просто не мог найти оригинал. Он работает с MonoGame / C #, что было достаточно для меня.
ashes999
Но есть оригинальный порт, верно? Разве это не должно быть такой простой функцией? В любом случае, я не использую MonoGame, просто XNA. Вы все еще порекомендуете мне использовать этот порт?
Даниэль Рибейро
Я должен был дать правильный ответ ssb, но большое спасибо за это. Я обязательно попаду в этот порт! Большое спасибо!
Даниэль Рибейро
1
@DanielRibeiro ах, понятно. Я думаю, что этот метод не существует в MonoGame, поэтому я и использовал этот подход. Ура, хотя.
ashes999