При создании сустава во время выполнения объект телепортируется

У меня есть два объекта, и когда расстояние между ними меньше 10, я создаю соединение:

var joint_def = new box2d.b2RevoluteJointDef();
joint_def.bodyA = body1;
joint_def.bodyB = body2;
joint_def.localAnchorA = new box2d.b2Vec2(0, 0);
joint_def.localAnchorB = new box2d.b2Vec2(0, 0);
world.CreateJoint(joint_def);

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

Есть идеи? Спасибо.


person Rok Povsic    schedule 30.12.2013    source источник


Ответы (1)


Я считаю, что у вас есть две проблемы:

Проблема №1. LocalAnchorA и localAnchorB — это точки, в которых должно быть соединение. Это будет точка в мировом пространстве, отображенная в локальной системе координат соответствующих тел. Вы можете сделать это вручную или с помощью функции в join_def (по крайней мере, так это работает в С++):

Автоматически:

b2RevoluteJointDef jointDef;
b2Vec2 anchor = _body->GetWorldCenter();
jointDef.Initialize(_body, otherBody, anchor);
jointDef.collideConnected = true;
_world->CreateJoint(&jointDef);

Вручную:

   b2RevoluteJointDef jointDef;
   b2Vec2 anchor = _body->GetWorldCenter();
   jointDef.bodyA = _body;
   jointDef.bodyB = otherBody;
   jointDef.localAnchorA = _body->GetLocalPoint(anchor);
   jointDef.localAnchorB = otherBody->GetLocalPoint(anchor);
   jointDef.referenceAngle = otherBody->GetAngle() - _body->GetAngle();
   _world->CreateJoint(&jointDef);

Вы инициализируете опорные точки (оба) с помощью b2Vec2 (0,0). Я собираюсь использовать этот код, чтобы продемонстрировать, как выглядит разница:

Когда у вас есть обе опорные точки, определенные в локальном пространстве каждого тела:

введите здесь описание изображения

Обратите внимание, что буква «Т» вращается, но другое тело не движется. Но сустав удерживает их на повернутом расстоянии друг от друга.

Если у вас установлены обе локальные точки привязки (0,0):

введите здесь описание изображения

В общем, если у вас есть метод Initialize(...), используйте его для создания соединения.

Проблема №2: если вы начнете с тел, находящихся на расстоянии 10 м друг от друга, и именно там вы создадите свое вращательное соединение, там они и останутся. Если вы хотите, чтобы они начали двигаться навстречу друг другу... Я думаю, что самый простой способ сделать это (и я сделал это...см. здесь) состоит в том, чтобы присоединить соединение веревки между ними, а затем при каждом "обновлении" физического цикла делать что-то подобное (зная, что соединение веревки является первым и единственный сустав, соединенный с телом):

  b2JointEdge* jointEdge = GetBody()->GetJointList();
  b2RopeJoint* rope = (b2RopeJoint*)jointEdge->joint;
  rope->SetMaxLength(rope->GetMaxLength()-_ropeClimbDistPerUpdate);

Когда длина веревки станет меньше некоторого допуска, подключите вращающееся соединение. Довольно неплохо получается заставить пауков прыгать с астероидов...

ПРИМЕЧАНИЕ Вы также можете использовать b2DistanceJoint вместо b2RopeJoint. Соединение веревки ограничивает максимальное расстояние, а дистанционное соединение ограничивает фиксированное расстояние. Для этой ситуации должно получиться примерно так же. Соединение веревки может отсутствовать в других портах box2d.

Это то, что вам было нужно?

person FuzzyBunnySlippers    schedule 31.12.2013
comment
Спасибо за ответ. Проблема № 1 на самом деле не была проблемой, я хочу, чтобы один объект был поверх другого, так что все в порядке. Проблема № 2 дала мне путь к решению. Я не мог использовать Rope Joint, так как он не поддерживается в Box2dWeb. Вместо этого я использовал Distance Joint и медленно сокращал расстояние между объектами, используя SetLength() на стыке. - person Rok Povsic; 31.12.2013
comment
Это хорошее замечание о дистанционном соединении. Я изменю ответ (для других), чтобы добавить это как вариант. Рад, что это сработало. - person FuzzyBunnySlippers; 31.12.2013