простий алгоритм зіткнення прямокутника 2D, який також визначає, з яких сторін стикаються прямокутники?


16

Я спочатку спробував здійснити прямокутне перехрестя, яке добре працює. Однак, коли мені доводиться застосовувати фізичну систему, таку як вектори швидкості, прискорення та спрямованості, мені доведеться знайти спосіб визначити, яка сторона прямокутників стикається. Зараз у моїй системі немає обертового прямокутника, тому це спростило проблему. Однак я не зміг знайти простий спосіб визначити, яка сторона прямокутника зіткнулася. Я колись раніше займався цією проблемою, але зазнав невдач.

Що я робив у минулому, це визначити відстань між кожною паралельною прямокутною стороною і перевірити, чи відстань близька до 0 (використовуйте деякий початково визначений діапазон відстані) або дорівнює 0. Однак для арифметики з плаваючою комою це виявляється нестабільним, оскільки невідомого часу. Колись прямокутники фактично перетинатимуться один до одного, перш ніж він відповідатиме заданому діапазону.

З іншого боку, я думав про нерест декількох прямокутників, кожен прямокутник для кожної сторони. Однак, подумавши ще раз, було б те саме, що мати паралельну сторону з перевіркою дальності відстані, тільки що ця відстань є шириною кожного міні-прямокутника.

Тому будь-яка пропозиція до цієї проблеми?


Використовуєте дискретні чи постійні оновлення позицій? (ви оновлюєте свою швидкість прискоренням раз на кожен кадр, а потім обчислюєте позицію, або використовуєте функцію для екстраполяції позиції)
Кейсі Кубалл,

Відповіді:


24

Адаптований з моєї відповіді на "З якої сторони потрапив удар?" :

Я пропоную обчислити суму Міньковського B і A, яка є новим прямокутником, і перевірити, де центр прямокутника A лежить відносно цього нового прямокутника (щоб знати, чи відбувається зіткнення) та його діагоналей (щоб знати, де зіткнення) стається):

float w = 0.5 * (A.width() + B.width());
float h = 0.5 * (A.height() + B.height());
float dx = A.centerX() - B.centerX();
float dy = A.centerY() - B.centerY();

if (abs(dx) <= w && abs(dy) <= h)
{
    /* collision! */
    float wy = w * dy;
    float hx = h * dx;

    if (wy > hx)
        if (wy > -hx)
            /* collision at the top */
        else
            /* on the left */
    else
        if (wy > -hx)
            /* on the right */
        else
            /* at the bottom */
}

1
Я хотів би додати, що "верх" і "низ" відносяться до вашої системи координат. Наприклад, у моїй грі (0,0) знаходиться вгорі ліворуч, тому вони перевернуті з вашого прикладу. Просто щось пам’ятати.
Нейкос

чудове рішення, дуже добре працював для моїх потреб.
Opiatefuchs

1
Чи є якийсь глюк, коли dx стає 0 або dy стає 0 або і те й інше? Дозвольте це пояснити ... якщо dx = 0 && dy == 0, це означає, що обидва прямокутники мають однакове походження, то алгоритм повертається донизу за замовчуванням? якщо будь-який з них дорівнює 0, то очікується правильний результат. Отже, я думаю, цей алгоритм є правильним, за винятком випадків, коли dx == 0 && dy == 0, який має бути невизначеним, а не дном. Отже, будьте обережні та дякую.
Прасант

1
Тепер мені було цікаво, що відбувається, коли dx == dy, w == h ... тоді також код вирішує, що результат є однією стороною, коли він насправді невизначений .. уявіть два квадрати, що перетинаються таким чином, що центр одного квадрата знаходиться у кут іншої площі, а центр другої площі - на куті першого квадрата. Тут бік повинен бути невизначеним - це не правильно чи знизу. Це обоє ?!
Прасант
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.