Отримайте деталі зіткнення від 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

Хтось дав мені право на stackoverflow
Даніель Рібейро

Гаразд, із поверненим Прямокутником, як я можу перевірити положення весла, що зіткнувся з м'ячем?
Даніель Рібейро

Якщо ви знаєте , що лопатка і м'яч пересічні потім використовувати інформацію про місцезнаходження лопастного прямокутника , який ви перевірили в першу чергу, тобто rectangle.Xабо , rectangle.Yабо все , що ви хочете отримати доступ.
ssb

4

Оновлення: Якщо ви використовуєте MonoGame, то станом на 3,0 бета-версії Rectangle Rectangle.Intersect(rectangle, rectangle)не існує. Ви можете використати наведений нижче код із набору платформ XNA.


Ви можете завантажити Starter Kit XNA Platformer ( перенесений на 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);
        }
}

Дуже дякую за це посилання. Чи можу я запитати вас, чому вам потрібно було використовувати модифіковану версію? Це портовий чиновник?
Даніель Рібейро

@DanielRibeiro Я перевірив свою історію і, мабуть, не змінив її. Порт неофіційний; Я просто не міг знайти оригінал. Він працює з MonoGame / C #, що було досить добре для мене.
ashes999

Але є оригінальний порт, правда? Хіба це не повинно бути такою простою особливістю? У будь-якому випадку, я не використовую MonoGame, а лише XNA. Ви все-таки рекомендуєте мені використовувати цей порт?
Даніель Рібейро

Мені довелося встановити правильну відповідь ssb, але дуже дякую за це. Я точно буду потрапляти в цей порт! Дуже дякую!
Даніель Рібейро

1
@DanielRibeiro ах, бачу. Я думаю, що цього методу не існує в MonoGame, тому я в кінцевому підсумку використовував такий підхід. Ура, хоча.
ashes999
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.