Коллизии: AABB, OBB, круговые и полигональные

Что такое коллизия и зачем она нужна?

Представь, что в игре персонаж подходит к стене — и не проходит сквозь неё 🧱. Пуля попадает во врага — и наносит урон 💥. Всё это работает благодаря коллизиям (столкновениям). Коллизия — это обнаружение пересечения между объектами. Без неё игра просто развалилась бы!

🎮 Коллизии используются не только для физики, но и для определения клика по кнопке, попадания луча и многого другого!

Сегодня мы разберём четыре основных типа коллизий, которые чаще всего используются в геймдеве.


AABB (Axis-Aligned Bounding Box)

Это самый простой и популярный вид коллизии. AABB — это прямоугольник, стороны которого строго параллельны осям X и Y 📦. Его очень легко проверить на пересечение!

Как представить AABB? Просто запомни две точки: левый нижний угол и правый верхний.

min_x = 10
min_y = 10
max_x = 20
max_y = 20

Два AABB пересекаются, если:

  • Правый край первого объекта левее левого края второго? → Нет пересечения ❌
  • Левый край первого объекта правее правого края второго? → Нет пересечения ❌
  • Верхний край первого объекта ниже нижнего края второго? → Нет пересечения ❌
  • Нижний край первого объекта выше верхнего края второго? → Нет пересечения ❌
  • Во всех остальных случаях — есть пересечение! ✅

В коде это выглядит так:

def check_aabb_collision(box1, box2):
    if (box1.max_x < box2.min_x or box1.min_x > box2.max_x or
        box1.max_y < box2.min_y or box1.min_y > box2.max_y):
        return False
    return True

💡 AABB не поворачивается вместе с объектом! Он всегда параллелен осям. Это и плюс (простота), и минус (неточность для повёрнутых объектов).

Задача на AABB

У нас есть два прямоугольника:

  • Первый: от (2, 3) до (5, 6)
  • Второй: от (4, 5) до (7, 8)

Сталкиваются ли они?

Решение

  1. Сравниваем по X: max_x первого = 5, min_x второго = 4 → 5 > 4, и min_x первого = 2, max_x второго = 7 → 2 < 7 ✅
  2. Сравниваем по Y: max_y первого = 6, min_y второго = 5 → 6 > 5, и min_y первого = 3, max_y второго = 8 → 3 < 8 ✅
  3. Ни одно из условий непересечения не выполнилось → коллизия есть! 🎯

OBB (Oriented Bounding Box)

А что, если наш объект повёрнут? 📐 AABB уже не справится, потому что он будет слишком большим и неточным. На помощь приходит OBB — повёрнутый прямоугольник.

OBB учитывает поворот объекта, поэтому его грани не параллельны осям. Проверка коллизии сложнее, но точнее.

Самый популярный алгоритм для проверки OBB — Separating Axis Theorem (SAT) — теорема о разделяющей оси. Если между двумя объектами можно провести прямую, которая их разделит — коллизии нет.

📐 Для OBB достаточно проверить 4 оси (нормали к сторонам каждого прямоугольника).

Алгоритм SAT (упрощённо):

  1. Спроецировать оба многоугольника на ось.
  2. Если проекции не пересекаются хотя бы на одной оси — коллизии нет.
  3. Если пересекаются на всех осях — коллизия есть.

Реализация OBB сложнее, но она даёт точность для повёрнутых объектов!


Круговые коллизии

С кругами всё гораздо проще! 🎯 Нужно лишь проверить расстояние между центрами.

Формула проверки коллизии двух кругов:

distance = sqrt((x2 - x1)**2 + (y2 - y1)**2)
if distance < (radius1 + radius2):
    коллизия есть!

Чтобы избежать дорогого вычисления квадратного корня, часто сравнивают квадраты расстояний:

distance_sq = (x2 - x1)**2 + (y2 - y1)**2
if distance_sq < (radius1 + radius2)**2:
    коллизия есть!

Задача на круговые коллизии

Два круга: первый в точке (0, 0) с радиусом 5, второй в точке (8, 0) с радиусом 3. Есть ли коллизия?

Решение

  1. Вычисляем расстояние между центрами: 8 - 0 = 8
  2. Сумма радиусов: 5 + 3 = 8
  3. Расстояние (8) равно сумме радиусов (8) → круги касаются, но не пересекаются! Это крайний случай, который обычно не считают коллизией. ❌

🌀 Круги отлично подходят для шаров, пуль, зон приближения — там, где не нужна высокая точность по форме.


Полигональные коллизии

Самый точный и сложный тип — когда коллайдер повторяет форму объекта 🔺. Используется для сложных форм, например, машин или персонажей.

Полигон (многоугольник) задаётся списком вершин. Проверка коллизии обычно тоже использует SAT, но осей уже больше — по числу нормалей к сторонам каждого полигона.

Основные шаги проверки для двух полигонов:

  1. Взять первую ось (нормаль к стороне первого полигона).
  2. Спроецировать оба полигона на эту ось.
  3. Если проекции не пересекаются — коллизии нет.
  4. Повторить для всех осей первого полигона.
  5. Повторить для всех осей второго полигона.
  6. Если на всех осях проекции пересекаются — коллизия есть.

⚠️ Это computationally expensive (вычислительно дорого)! Поэтому для сложных моделей часто используют комбинацию: сначала проверяют простые коллайдеры (AABB/круги), а если они пересеклись, тогда уже проверяют полигональную коллизию.


Скрыть рекламу навсегда

🌱 Индвидидулаьные занятия

Индивидуальные онлайн-занятия по программированию для детей и подростков

Личный подход, без воды, с фокусом на понимание и реальные проекты.

🚀 Записаться на занятие