Разрешить персонажу ходить по стенам и потолку в Box2D? - PullRequest
1 голос
/ 03 ноября 2011

Я хочу сделать игру, которая происходит в космосе, используя Box2D для физики.Одна из вещей, которую я хочу, чтобы главный герой, которого вы контролируете, была в состоянии делать это - ходить вверх ногами по потолку или боком по стенам.Я хочу, чтобы стены и / или потолки могли быть под любым углом, поэтому, независимо от формы комнаты, он всегда сможет придерживаться ее.

Пока я хочу, чтобы персонаж былЯ могу, чтобы все враги, предметы, объекты и т. д. имели нормальную гравитацию, отталкивая их к земле.

Возможно ли это в Box2D?Если это так, что будет лучшим способом заставить это работать?

Ответы [ 2 ]

1 голос
/ 12 ноября 2013

Это полностью возможно в Box2d, но требует некоторой работы, чтобы все заработало.

Игра, над которой я работаю, под названием «Космические пауки должны умереть!», Требовала, чтобы «космические пауки» могли ходить по астроидам, прыгая между ними.

Первое, что вам нужно, это путевые точки.Это точки на теле, которые вы хотите передвигать, или в вашем случае, прямо возле ваших стен, по которым вы хотите, чтобы ваш персонаж двигался по ним.Наличие «статичности» точек (не на движущемся теле) значительно сокращает объем работы.

Предположим, вы хотите перемещаться между двумя точками p0 и p1 с течением времени T. Ваш временной шаг dT (фиксированный)).Соблазнительно использовать SetTransform (...) на теле, делая что-то вроде:

// Initialize for new points
int steps = T/dT;
Vec2 toTarget = p1-p0;
toTarget.Normalize();
int stepsTaken = 0;
float32 bodyAngle = atan2f(toTarget.y,toTarget.x)

// Each time step
stepsTaken++;
Vec2 pos = p0 + stepsTaken*dT*toTarget;
body.SetTransform(pos,bodyAngle);
if(stepsTaken >= steps)
{  
   // Set up next set of points.
}

ОДНАКО, если вы сделаете это, я думаю, вы обнаружите, что физический движок больше не взаимодействует с вашим теломдля столкновений.Я полагаю, что это потому, что SetTransform (...) заставляет двигатель «пропустить удар» в отношении обнаружения столкновений.

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

Это код из проекта, в котором я делал это:

 void CreateNextMovingJoint(float32 motorStrength = 1.0f)
   {
      b2PrismaticJointDef jointDef;
      // We need to figure out some geometry here.
      _pathIter = _pathDataList.begin();
      PATH_DATA_T& pd = *_pathIter;
      _pathIter++;
      // Anchor
      Vec2 pAnchor = pd.point;
      // End point of the anchor, used for the axis.
      Vec2 pEnd = pd.point + pd.distToNext[_direction]*pd.normalAlongPath[_direction];
      jointDef.bodyA = _bodyMovingOn;
      jointDef.bodyB = _bodyMoving;
      jointDef.localAnchorA = pAnchor;
      jointDef.localAnchorB = Vec2(0.0,0.0);
      jointDef.localAxisA = pEnd-pAnchor;
      jointDef.referenceAngle = 0;

      jointDef.enableMotor = true;
      jointDef.enableLimit = true;
      jointDef.motorSpeed = _maxSpeed;
      jointDef.maxMotorForce = motorStrength*(_maxSpeed/4)*_bodyMoving->GetMass();
      jointDef.lowerTranslation = -0.1*pd.distToNext[_direction];
      jointDef.upperTranslation = 1.1*pd.distToNext[_direction];
      jointDef.collideConnected = true;
      _bodyMoving->GetWorld()->CreateJoint(&jointDef);
   }

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

Это часть большой базы кода, но идея должна быть хорошо представлена ​​здесь.В моем случае я сохранил все данные для каждого сегмента точка-точка в структуре под названием PATH_DATA_T.Был список из них, который я повторил.Когда паук приближается к следующей точке, итератор переходит к следующему элементу и обрабатывает его.Это работало ОЧЕНЬ хорошо ( см. Видео здесь ).

Было ли это полезно?

0 голосов
/ 04 ноября 2011

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

Отменить гравитацию для одного тела очень легко, подробности см. Здесь: http://www.iforce2d.net/b2dtut/custom-gravity

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

...