Физический движок: взгляд изнутри. Часть 2

Это вторая часть статьи о физических 2D движках. Сегодня мы рассмотрим виды физических тел. Поговорим о том, как лучше найти баланс между реалистичностью ваших игр и невозможностью играть в них. Также обратим внимание на традиционные ограничения большинства готовых решений и почему не стоит добавлять в вашу игру вогнутые тела. А напоследок мы отметим основные свойства объектов физического мира.

Основные функции движков и наиболее популярные готовые решения мы рассмотрели в первой части статьи, которую вы можете найти здесь.

Обратите внимение, что для этой статьи уже доступно продолжение: «Физический движок. Часть 3»

От спрайта до физического тела

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

В этом отрывке мы попросту создаем спрайт:

… и вызываем метод коллизии между двумя спрайтами:

Границы физических тел

Физический объект на самом деле является простой фигурой, которая определят приблизительный размер и форму вашего спрайта (или ее активной части). Рассмотрим следующую картинку:

projectile-BasicPhysicsBodies-rus

Физическое тело по умолчанию не определено для спрайта, исходя из ее форм и размеров. Также следует обратить внимание на то, что само по себе тело невидимо (естественно, до тех пор, пока вы не включите режим отладки, если это предусмотрено движком). Границы тела задаются пользователем динамически. Зачастую они представляют из себя простые фигуры, которые можно отрисовать программно, средствами самого движка. Но если ваш спрайт имеет сложную форму и вам требуется максимальная точность, то вы можете воспользоваться сторонними программами для построения границ спрайта. После создания физического тела вам остается только прикрепить его к спрайту и отдать на растерзание физическому движку.

Спрайт может быть еще и составным. Например, герой с мечом. Было бы логично создать два физических тела: для самого героя и для его оружия, которым он восстанавливает справедливость. Таким образом, вы можете прикрепить два физических объекта к одному спрайту. А обрабатывать коллизии вы можете, например, так:

Калибровка границ физического тела

Возможно вы захотите сделать физическое тело игрока чуть меньше, чем оно есть на самом деле. Есть по крайней мере две причины для этого:

Улучшение визуальной коллизии

Если вы создадите для игрока физическое тело меньшего размера, то когда он будет сталкиваться с каким-то игровым объектом, спрайт героя перекроет спрайт коллайдируемого объекта. И это будет выглядеть превосходно. А в дополнение отмечу то, что вы должны правильно настроить z-параметр для всех спрайтов (z-параметр — это очередность вставки объекта на сцену; чем оно больше, тем выше будет находиться объект в игре).

Справедливость к игроку

Вы должны помнить, что создавая физические тела для игровых объектов, вы не должны быть несправедливым. Ограничивайте тела так, как они изображены на спрайте. Посмотрите на изображение выше. Крылья ракет не входят в границу коллайдируемой части объекта. Если игрок умудрится попасть туда, то столкновения как такового не произойдет, соответственно, урон врагу не будет нанесен. Вы можете подумать, что этот факт незначительный, но вы ошибаетесь.

С другой стороны, мы должны быть не только справедливы к игроку, но и всячески помогать ему (в разумных пределах, разумеется). Вы можете сделать физическое тело врага чуть больше, чем оно есть на самом деле. В таком случае игроку будет легче попасть в него. Этот вариант лучше, чем если бы делать не коллайдируемое крыло для ракеты. Но будьте осторожны, не переусердствуйте!

Традиционные ограничения 2D движков

Существует два основных типа физических тел:

  • Основанные на границах (edge-based bodies)
  • Основанные на объеме (volume-based bodies)

Тела, основанные на границах, статические. Они создаются при помощи линий, которые обрамляют игровой объект.

А вот тела, основанные на объеме, имеют, как это ни странно, объем и массу. Они могут быть как динамическими, так и статическими. Так как эти тела обладают массой, другие объекты отскакивают от них, получив некоторую силу. Volume-based тела можно создать 4 видов:

  1. Круг
  2. Прямоугольник
  3. Цепь
  4. Комплексный полигон

Однако есть некоторые ограничения в использовании таких тел. Вот два из них:

Выпуклость и вогнутость

Как ясно из заголовка, первое ограничение заключается во внешнем виде физического тела.

projectile-BasicPhysicsOutlineComp-rus

Нельзя использовать фигуры вогнутые. Вернее не так. Будем откровенны. Их можно использовать, однако стоимость обработки вогнутых тел настолько высока, что ее даже не логично использовать. Более того, коллизия обработается совсем нереалистично. Но как тогда быть? Ответ очевиден: используйте комбинацию из нескольких выпуклых фигур и получите вогнутую. Соединяются такие тела при помощи «статического сустава» (static joint). Суставы — еще одна не менее интересная возможность физических движков, однако не будем выходить за рамки текущей темы.

Твердые физические тела

Если в реальном мире мячик (например, футбольный) удариться об стенку, то мы увидим нечто похожее на изображение ниже:

projectile-RigidBodyExample

Спрайт вашего персонажа может пройти такую деформацию. Но его физическое тело сделать это не способно. Да, вы можете изменить свойство «bounciness» тела, однако на самом деле форма тела не поменяется. Почему? Да потому, что физическое тело известно как твердое. А твердое тело не может сплющиться (по крайней мере настолько, чтобы мы это увидели невооруженным взглядом).

Свойства физического тела

Давайте кратко рассмотрим некоторые полезные свойства физического тела из великого множества.

  1. Restitution (упругость). Иными словами, это свойство тела деформироваться под действием внешних сил.
  2. Density (плотность). Используется для описания тел (например, плотность кирпичика будет больше, чем мяча).
  3. Friction (трение). Это свойство тела показывает, насколько оно скользкое. Используется, например, в случаях, когда нужно описать поверхность. На льду персонаж будет скользить, а на асфальте — нет.
  4. Если тело динамическое (dynamic), то силы, приложенные к этому телу, будут воздействовать на него (например, двигать). Если же статическое (static) — объект останется неподвижным.
  5. Rotation (возможность вращения). Это свойство булевское: когда оно равно true, тело может вращаться. Иначе — угол вращения не изменится. Учтите, что все остальные силы все равно будут воздействовать на объект.

В большинстве физических движков свойств гораздо больше. Однако нам достаточно и этих, чтобы начать работу с ними.

Движение

В моделируемой физике тела двигаются от применения к ним сил и импульсов.

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

Основным отличием силы от импульса является то, что силой мы придаем ускорение (которое нам придется затем убрать), а импульсом меняем мгновенную скорость тела.

А на этом все. Об основах физических 2D движков мы рассказали. В следующей статье мы закрепим пройденный материал и применим новые знания на практике.

Перевод статьи «What’s in a Projectile Physics Engine?».