Проверка столкновений

Xtreme3D

Урок 11
Проверка столкновений

Уровень: средний
Версия Xtreme3D: 3.0.x
Автор урока: Gecko

В играх очень часто требуется определить факт столкновения двух объектов. Ими могут быть, к примеру, персонаж и платформа, снаряд и цель и т.д. На обнаружении столкновений основана логика шутеров, платформеров, симуляторов, ролевых игр и некоторых стратегий. При этом далеко не всегда требуется обнаружить точное пересечение двух полигональных мешей - достаточно протестировать на пересечение их ограничивающие сферы (Bounding Sphere) или параллелепипеды (Bounding Box). Xtreme3D включает удобные инструменты, позволяющие вам сделать это.

Функции проверки столкновений в Xtreme3D начинаются на "ObjectCheck..." и оперируют ограничивающими сферами и параллелепипедами объектов, которые вычисляются движком автоматически, в зависимости от объема, который занимает их геометрия. Ограничивающие параллелепипеды (которые в этих функциях называются Cube) выровнены по локальным координатным осям объекта - то есть, могут вращаться вместе с ним. Такие параллелепипеды часто называют Oriented Bounding Box, или сокращенно OBB. Функции возвращают истину (1), если обнаружено пересечение, и ложь (0) в противном случае.

Xtreme3D включает следующие функции проверки столкновений:
ObjectCheckSphereVsSphere, ObjectCheckSphereVsCube, ObjectCheckCubeVsCube, ObjectCheckCubeVsFace, ObjectCheckFaceVsFace. Последние две из них оперируют объектами типа Freeform - соответственно, позволяют обнаружить пересечение ограничивающего параллелепипеда одного объекта с полигональной моделью другого, а также пересечение двух моделей. Эта проверка довольно медленная, поэтому рекомендуем оптимизировать ее использование - например, осуществлять точную проверку между моделями только в том случае, если обнаружено столкновение между их ограничивающими сферами:

if ObjectCheckSphereVsSphere(obj1, obj2)
{
  if ObjectCheckFaceVsFace(obj1, obj2)
  {
    // делаем что-то
  }
}

Эти функции полезны, когда нужно выполнить дискретную проверку - то есть, когда можно допустить, что объекты движутся с небольшими скоростями. Если скорости высокие, и объект за один шаг игрового времени пролетает расстояние, превышающее размер другого объекта, дискретная проверка может запросто не сработать. Универсального решения этой проблемы до сих пор нет, но существуют различные упрощенные методы. Самый простой - метод "бросания лучей" (Ray Casting). В Xtreme3D есть достаточно эффективная реализация этого метода. Из центра объекта выпускается луч в направлении Direction этого объекта. Затем на пересечение с этим лучом проверяется целевой объект, один или несколько. Таким образом, можно сымитировать движение пули (при допущении, что она движется с бесконечной скоростью) - мгновенно обнаружить точку, в которую она попадет. Также при помощи "бросания лучей" можно определить высоту земли под персонажем, что необходимо для реализации прыжков. Кроме того, данный метод незаменим для построения логики взаимодействия персонажа с интерактивными объектами и триггерами - представьте, например, шутер, RPG или квест от первого лица, где игрок может подбирать предметы и нажимать на рычаги, кликая по ним мышью. Для этого можно оценить расстояние между игроком и объектом, а затем применить "бросание лучей":

if ObjectGetDistance(player, item) <= 1.0
{
  if ObjectRaycast(player, item)
  {
    hit_x = ObjectGetCollisionPosition(0);
    hit_y = ObjectGetCollisionPosition(1);
    hit_z = ObjectGetCollisionPosition(2);
  }
}

Что самое приятное, "бросание лучей" в Xtreme3D полностью совместимо с объектами Freeform и выдает корректные результаты при любой трансформации объектов.