Главная
Блог разработчиков phpBB
 
+ 17 предустановленных модов
+ SEO-оптимизация форума
+ авторизация через соц. сети
+ защита от спама

Взрывы в Box2D

Anna | 24.06.2014 | нет комментариев
В этой статье мы разглядим несколько видов взрывов в физическом движке Box2D.
Симуляция взрыва сводится к нахождению тел, которые находятся в радиусе действия взрывной волны и использовании силы к ним, Дабы отбросить их от центра взрыва.Мы расмотрим три вида взрывов различной трудности:

  • Нахождение тел в радиусе взрыва
  • Raycast – нахождения тел в радиусе лучей
  • Частицы – распространение многих маленьких тел от эпицентра взрыва


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

Использование толчка

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

Все описанное выше дозволено выразить дальнейшим кодом:

void applyBlastImpulse(b2Body* body, b2Vec2 blastCenter, b2Vec2 applyPoint, float blastPower)
{
      b2Vec2 blastDir = applyPoint - blastCenter;
      float distance = blastDir.Normalize();
      // Пренебрежение тел, которые находятся в центре взрыва
      if ( distance == 0 )
          return;

      float invDistance = 1 / distance;
      float impulseMag = blastPower * invDistance * invDistance;
      body->ApplyLinearImpulse( impulseMag * blastDir, applyPoint );
}

Нахождение тел в радиусе взрыва

Самый примитивный способ реализации взрывов: обнаружить все тела внутри определенного радиуса взрыва касательно его центра. Немножко уточнения: нам необходимы тела с ихними центрами массы в пределах указанного диапазона взрыва. Для этих целей в Box2D есть способ QueryAABB:

MyQueryCallback queryCallback;
b2AABB aabb;
aabb.lowerBound = center - b2Vec2( blastRadius, blastRadius );
aabb.upperBound = center   b2Vec2( blastRadius, blastRadius );
m_world->QueryAABB( &queryCallback, aabb );

// Посмотреть все обнаруженные тела и предпочесть только те, у которых центр масс входит в радиус взрыва
for (int i = 0; i < queryCallback.foundBodies.size(); i  )
{
      b2Body* body = queryCallback.foundBodies[i];
      b2Vec2 bodyCom = body->GetWorldCenter();

      //ignore bodies outside the blast range
      if ( (bodyCom - center).Length() >= m_blastRadius )
          continue;

      applyBlastImpulse(body, center, bodyCom, blastPower );
}

Давайте посмотрим на итог от такой реализации взрыва. На картинке указаны тела, которые получат толчок позже взрыва:

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

Объекты по обеим сторонам от центра взрыва имеют идентичную массу, но тела справа получат толчок в 4 раза огромнее, чем тело слева.

Raycast способ

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

for (int i = 0; i < numRays; i  )
{
      float angle = (i / (float)numRays) * 360 * DEGTORAD;
      b2Vec2 rayDir( sinf(angle), cosf(angle) );
      b2Vec2 rayEnd = center   blastRadius * rayDir;

      RayCastClosestCallback callback;
      m_world->RayCast(&callback, center, rayEnd);
      if ( callback.m_body ) 
          applyBlastImpulse(callback.body, center, callback.point, (m_blastPower / (float)numRays));
}

Обратите внимание, мы разделяем силу взрыва на число лучей. Сделано это для того Дабы было легче подобрать число лучей без метаморфозы всеобщей силы толчка взрыва. Давайте посмотрим на взрыв с применением 32 лучей:

Значительно отменнее: взрывная волна не проходит через платформы. В

 

Источник: programmingmaster.ru

 

Оставить комментарий
Форум phpBB, русская поддержка форума phpBB
Рейтинг@Mail.ru 2008 - 2017 © BB3x.ru - русская поддержка форума phpBB