2014-01-16 3 views
0

Я создаю свое собственное приложение для игр с использованием Box2D, и у меня возникли некоторые проблемы. Мне удалось отобразить все те тела, которые я хотел, переместив их, но я должен уделить большое значение правильному их перемещению. Например вот мое определение тела игрока:Значения линейного импульса

bodyDefPlayer = new BodyDef(); 
    bodyDefPlayer.type = BodyType.DynamicBody; 
    bodyDefPlayer.position.set(positionX, (positionY * tileHeight) + 50); 
    playerBody = world.createBody(bodyDefPlayer); 
    polygonPlayer = new PolygonShape(); 
    polygonPlayer.setAsBox(50, 50); 
    fixturePlayer = new FixtureDef(); 
    fixturePlayer.shape = polygonPlayer; 
    fixturePlayer.density = 0.8f; 
    fixturePlayer.friction = 0.5f; 
    fixturePlayer.restitution = 0.0f; 
    playerBody.createFixture(fixturePlayer); 
    playerBody.setFixedRotation(true); 

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

Vector2 vel = this.player.playerBody.getLinearVelocity(); 
    Vector2 pos = this.player.playerBody.getWorldCenter(); 
    player.playerBody.applyLinearImpulse(new Vector2(vel.x + 20000000, vel.y * 1000000), pos, true); 

Как вы можете видеть мои ценности довольно высоки плюс игрок ISN '' делая кривую, когда он идет вниз, но больше идет прямо вниз, когда он может.

Я хотел бы иметь некоторую помощь, пожалуйста :)

Спасибо!

ответ

2

Кажется, что вы используете линейный импульс, когда вам нужно просто применить силы. Линейный импульс «приносит» тело с большой силой, чтобы придать ему здоровенную мгновенную скорость. Это хорошо, если вы попадаете в мяч для гольфа (большая сила, небольшое время) или имитируете выстреливаемую пулю, но она не выглядит хорошей для движения реальных тел.

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

void ApplyThrust() 
    { 
     // Get the distance to the target. 
     b2Vec2 toTarget = GetTargetPos() - GetBody()->GetWorldCenter(); 
     toTarget.Normalize(); 
     b2Vec2 desiredVel = GetMaxSpeed()*toTarget; 
     b2Vec2 currentVel = GetBody()->GetLinearVelocity(); 
     b2Vec2 thrust = desiredVel - currentVel; 
     GetBody()->ApplyForceToCenter(GetMaxLinearAcceleration()*thrust); 
    } 

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

Обратите внимание, что это НЕ изменяет ориентацию кузова. Для этого есть отдельная функция.

Обратите внимание, что исходный вопрос находится на Java (libgdx?). Это на C++, но общая идея применима и должна работать в любой реализации Box2d, используя ссылки вместо указателей и т. Д.

Существует кодная база с samples of doing this located here. You can read more about this code base in this post. Посмотрите видео ... Я подозреваю, что он сразу сообщит вам, если это информация, которую вы ищете.

Функция Нормализация, которая должна быть членом класса b2Vec2 является:

/// Convert this vector into a unit vector. Returns the length. 
float32 b2Vec2::Normalize() 
{ 
    float32 length = Length(); 
    if (length < b2_epsilon) 
    { 
     return 0.0f; 
    } 
    float32 invLength = 1.0f/length; 
    x *= invLength; 
    y *= invLength; 

    return length; 
} 

Это преобразует вектор в единичный вектор (длина = 1), указывая в том же направлении. ПРИМЕЧАНИЕ Это операция на месте. Он изменяет фактический объект b2Vec2, он не возвращает новый объект. Адаптируйте к Java по своему усмотрению.

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

+0

Привет, я просто попробовал то, что вы мне ответили. Поскольку это (я думаю), C++ я не могу его использовать. У меня возникли вопросы. Во-первых, у вас есть Vector2, который должен иметь 2 значения, и у вас есть только одна (первая строка). Во-вторых, что должно делать toTarget.Normalize()? После этого я понял, я попытался использовать ApplicationForceToCenter и, похоже, отлично работает, поэтому спасибо за советы :) – Kamigaku

+0

@ user2919009 Vec2 = b2Vec2 в box2d. Я конвертирую код. У меня просто есть typedef. Похоже, вы используете java (возможно, libgdx?). Код полностью применим ... вам просто нужно сделать небольшое преобразование для -> в "." оператор, я считаю. – FuzzyBunnySlippers

+0

Что должно делать toTarget.Normalize()? Редактировать: я только что проверил в сети, Vector2 в JAVA не имеет функции нормализации, я буду подробно проверять, что она делает, или я просто пропущу ее. – Kamigaku

2

Вы используете те же единицы измерения для графики и физики (в пикселях).Есть две причины, почему такой подход плохо:

  1. Это масштабируемые плохо на различных разрешениях
  2. Box2D настроен на работу с некоторым диапазоном значений (за счет точности с плавающей). Вы можете найти диапазон значений в руководстве Box2D. Они находятся в метрах, но как вы называете единицы, на самом деле не важно, так как Box2D не отслеживает единицы, а вместо этого использует значения. Например, вы можете сказать, что скорость тела составляет 10 метров в секунду или 10 футов в секунду. Для расчетов это не важно. Это станет важным, когда вы будете интерпретировать результат расчетов. Например, пройденная дистанция с течением времени: в первом случае это будут метры и на второй ноге. Но это не бизнес Box2D. Вы просто передать значения к нему (например, body.pos.set(2, 3) //no info about units here)

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

Смежные вопросы