SpriteKit — Имитация физики — Настройка свойств — Часть 12

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

mass — «масса» определяет, как силы влияют на тело и какой силы импульс будет передан при столкновении.
friction — определяет шероховатость поверхности тела. Оно используется для вычисления силы трения при контакте с телом
— Свойства linearDamping и angularDamping используются для расчета имитации силы трения среды. Например, оно может быть использовано для имитации воздуха или воды.
restitution свойство определяет, сколько энергии тело может принять во время столкновений. Вообщем, как сильно тело отскочит от чего либо.
allowsRotation определяет, могут ли силы придавать угловую скорость телу. Проще говоря, будет ли ваш спрайт крутиться после столкновения

Mass, area, density (Масса, площадь, плотность)
Вы должны установить массу для каждого физтела так, чтобы оно правильно реагировало на силы, приложенные к нему.
Свойства тела масса (mass), площадь (area) и плотность (density) взаимосвязаны. Когда вы инициализируете физтело, площать тела рассчитывается и никогда не меняется впоследствии. Масса и плотность могут меняться на основании следующей формулы:
масса = плотность х площадь

Поэтому при настройке свойств физтела, у вас есть два варианта:
1. Установить массу тела. При этом плотность автоматически скалькулируется. Этот подход наиболее полезен, когда вы хотите точно контролировать массу каждого тела на сцене.
2. Установить плотность тела. При этом масса расчитается автоматически. Этот подход наиболее полезен, когда у вас есть коллекция похожих тел, созданных с различными размерами. Например, если ваши физические тела были использованы для создания астероидов, вы можете дать всем астероидам одну плотность, а затем установить размеры каждого. Каждое тело автоматически вычисляет свою массу на основе его размера на экране.
Звучит все это не очень, но все просто.

Настройка свойств в процессе игры
Чаще всего, настроив физику тела один раз вам не приходится перенастраивать ее. Например, масса тела вряд ли изменится во время игры. Тем не менее, ни что не мешает вам изменить массу тела во время игры. Например:
— В симуляции реалистичного ракетного запуска, ракета расходует топливо и соответственно масса ракеты уменьшается. Чтобы реализовать это в Sprite Kit, вы можете создать класс ракеты у которого есть свойство Топливо. Во время расхода топлива, масса автоматически пересчитывается.
— Если ваша игра имитирует несколько сред (например вакуум,вода) и тела могут перемещаться между этими средами, вы можете обновлять свойства linearDamping и angularDamping при переходе между средами.

Настройка физики мира SKPhysicsWorld
Все физические тела в сцене являются частью мира, который представлен в Sprite Kit объектом SKPhysicsWorld прикрепленным к сцене. У физики мира есть две важных характеристики:
1. gravity — свойство определяет применяются ли ускорения тел на основе их объема. Если в вашем теле свойство affectedByGravity стоит как NO, телу все равно на этот параметр.
2. speed свойство определяет скорость, с которая применяется к симуляции в мире.
Как закончу писать про физику, сделаю наглядный пример со всей физикой. Если у вас есть предложения для примера по физике, пишите в комменты

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

Во-первых, вы можете контролировать скорость тела напрямую, устанавливая свойства velocity и angularVelocity. Например, летящий космический корабль выпускает ракету и она должна иметь начальную скорость звездолета плюс дополнительный импульс в направлении запуска. Вот один из вариантов расчета:

missile.physicsBody.velocity = self.physicsBody.velocity;
[missile.physicsBody applyImpulse:CGVectorMake(missileLaunchImpulse*cosf(shipDirection),missileLaunchImpulse*sinf(shipDirection))];

Ничего сложного, первая строка — задаем ракете скорость звездолета. И вторая строка, добавляем ракете импульс в направлении цели.

Итак, по умолчанию, силы которые применяются к телу включают в себя:
— Гравитационная сила
— Сила затухания, расчитывается в зависимости от импульсов переданных телу и физических свойст тела (масса, плотность и тд)
— Сила трения, расчитывается на основе контакта с другим телом в системе

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

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

Вы можете применять силу к телу одним из трех способов:
— Линейная сила, которая влияет только на линейную скорость тела.
— Угловая сила, которая влияет только на угловую скорость тела.
— Усилие, прилагаемое к точке на теле. Моделирование физики вычисляет отдельные изменения в угловой и линейной скорости тела, основанные на форме объекта и точки, где сила была применена.

Например, сила ускоряет ракету. Поскольку двигатели в задней части ракеты, сила прикладывается линейно к корпусу ракеты. Код ниже рассчитывает вектор тяги на основе текущей ориентации ракеты. Ориентация, это свойство zRotation соответствующего спрайта, оно может отличаться от ориентации физтела. Вот примерный код для применения ракетной тяги )

static const CGFloat thrust = 0.12;

CGFloat shipDirection = [self shipDirection];
CGVector thrustVector = CGVectorMake(thrust*cosf(shipDirection),
                                   thrust*sinf(shipDirection));
[self.physicsBody applyForce:thrustVector];

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

  • oleg

    как изменять направление physicsWorld.gravity в уже созданной сцене?
    например, я хочу чтобы при повороте устройства направление гравитации менялось
    physicsWorld.gravity = CGVectorMake(newDX, newDY); не меняет

    или может быть можно заменить гравитацию как-нибудь своей силой?
    спасибо!

    • oleg

      блин, затупил, все меняется )

  • андрей

    Добрый день. Вы могли бы написать статью про вектора, или что то иное, для замедления падения обьекта на который действует гравитация?

    • floMaster

      Сейчас пример доделываю, там подробнее напишу про вектора