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

20150316205239406_5215977

В этой статье мы рассмотрим использование физики для имитации броска снарядов (да, прямо как в Angry Birds). Мы обратим внимание на основы использования 2D физики, а также на создание физических тел, импульсов и сил. Не забудем отметить и наиболее популярные игровые движки для симуляции физических 2D миров.

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

Функции физического движка

Зачем нам использовать какой-то физический движок? И что это такое на самом деле?

Вообще физический движок очень полезен. Он позволяет сделать за нас две важные вещи:

  • Обнаружение столкновений (коллизий) между нашими игровыми объектами;
  • Имитация силы и движений в результате столкновений.

Обнаружение столкновений

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

Имитация силы

Что должно произойти после столкновения? Могут произойти различные явления: может прыгнуть персонаж, может прыгнуть какой-то другой игровой объект, а может вы просто будете двигаться в каком-то направлении. Все это выполняется движком за кадром. Но силы, которые может имитировать физический движок, не ограничены столкновениями. Существуют такие понятия, как гравитация и импульс. Они могут применяться к телам, даже если те не сталкивались. Также такие силы могут влиять на действия, которые происходят в игре, на движения героев и даже на сам мир.

projectile-BasicsForces

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

Выбор физического движка

На этом этапе у вас есть два варианта. Оба варианта имеют как достоинства, так и недостатки:

  1. Использовать существующий физический движок;
  2. Написать свою реализацию (с преферансом и куртизанками).

Использование существующего движка

Существуют несколько отличных готовых вариантов. Один из самых популярных движков для 2D игр это, безусловно, Box2D. Написан был изначально на C++, однако был портирован практически на все популярные языки программирования. Другим достаточно известным движком является Chipmink 2D, который используется как основной в таких фреймворках, как Cocos2D.

Написание своего движка

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

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

Цикл игры

Прежде чем рассматривать свойства и детали моделирования физики, давайте посмотрим на то, что происходит в каждом игровом кадре при подходе «в лоб»:

projectile-BasicLoop

Типичный цикл игры для каждого кадра будет проходит четыре шага в следующем порядке:

  • Вход в кадр;
  • Обновление игровой логики;
  • Симуляция физики;
  • Отрисовка кадра.

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

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

Фиксированная частота кадров против варьируемой

Давайте поговорим о частоте кадров: фиксированной (fixed rate) и варьируемой (frame dependent rate). Метод update вызывается один раз за кадр игровой сцены. Если ваш метод симуляции физики вызывается из метода update, то ваш физический мир будет зависеть от частоты кадров. Это может привести к нереалистичному поведению физических тел. В iOS этот эффект решается за счет использования булевского свойства usesPreciseCollisionDetection. Но что насчет других операционных систем?

Рассмотрим отрывок кода:

Этот код предназначен для компенсации проблем с дельта-значением времени. Актуально это будет в том случае, если во время игры вам позвонили. Тогда вы сможете при помощи такого алгоритма восстановить дельта-значение времени (для игры с 60 FPS).

Это на самом деле первый шаг в понятии работы физического движка. Да, предыдущий кусочек кода сделает нашу симуляцию более стабильной, но всех проблем он не решит. Для этого нам понадобится удалить вызов функции моделирования физики из цикла рендеринга игровой сцены, а затем создать фиксированный цикл. В течение этого цикла и будет работать симуляция физики. Например, если ваша игра рассчитана на работу в 60 кадров в секунду, то вы устанавливаете частоту моделирования физики в 60 раз в секунду. Такое разделение обязанностей позволит нам устранить множество проблем.

Подытожив, хочется сказать, что раз уж вы решили писать свой физический движок — будьте добросовестными и делайте все правильно. На этом первая часть нашей статьи заканчивается. В следующей части мы поговорим о физических телах и их свойствах, а также упомянем типичные ограничения физических движков.

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