Заметьте, что каждая фигура обязана иметь родительское тело (тело к которому она присоединена) даже если эта фигура статичная. Однако, вы можете присоединить все статичные фигуры к одному телу. Это было сделано для статичных тел для того, чтобы сделать код внутри Box2D единообразным, универсальным, уменьшив таким образом количество потенциальных ошибок.
Здесь вы можете увидеть общую структуру построение кода. Имена большей части типов в Box2D начинаются с префикса Ь2. Это сделано, чтобы уменьшить вероятность конфликтов имен с вашим кодом.
2.3. СозданиеДинамичногоТела(Dynamic Body)
Итак, у нас уже есть тело "земли". Для создания динамичного тела используется такая же техника. Основное отличие, кроме размеров, состоит в том, что мы должны установить для него множество параметров присущих динамичным объектам.
Сначала создадим тело, используя createBody:
b2BodyDef bodyDef;
bodyDef.position.Set(0.Of,
4.Of);
b2Body* body = world.CreateBody(SbodyDef);
Затем создаём фигуру-полигон и прикрепляем ее к телу. Заметьте, что плотность (density) тела установлена равной 1. По умолчанию она равна нулю. Коэффициент трения (friction) поставим 0.3. После присоединения фигуры вызовем метод SetMassFromshapes, чтобы пересчитать массу тела на основе данных о присоединенных
фигурах. Это такой тонкий намек на то, что вы можете присоединять к телу (body) больше чем одну фигуру (shape). Если масса тела после пересчета окажется нулевой, то тело становится статичным. Заметьте, что тела имеют нулевую массу по-умолчанию, именно поэтому мы не вызывали setMassFromshapes, когда создавали тело "земли".
b2PolygonDef shapeDef; shapeDef.SetAsBox(1.Of, l.Of); shapeDef.density = l.Of; shapeDef.friction = 0.3f; body->CreateShape(SshapeDef); body->SetMassFromShapes();
Ну вот, с инициализацией закончили. Теперь можно начинать процесс моделирования.
2.4. Моделирование физического мира (Box2D)
Теперь у нас есть "земля" и динамичное тело, давайте же заставим законы Ньютона делать их работу. Но сначала рассмотрим пару новых понятий.
Для моделирования движения тел Box2D использует численное дифференцирование (а точнее метод Эйлера). Выгляди это так: мир Box2D содержит функцию Step(float timeStep,int iterations), имеющую два аргумента: время, которое необходимо смоделировать в мире и количество итераций для разрешения взаимодействий между объектами.
Обычно, физические движки для игр используют timeStep не более 1/60 секунды (т.е. "частота кадров" расчета физики не менее 60Гц), такого интервала вполне достаточно для реалистичного моделирования физики в играх. Вы можете задать другой timeStep, но в таком случае вам придётся более осторожно настраивать параметры вашего мира. Поэтому мы не советуем вам сильно изменять timeStep. Но очень нежелательно связывать временной шаг с частотой смены кадров графической подсистемы (исключая случаи, когда это действительно необходимо). Задаем timeStep:
float32 timeStep = l.Of / 60.Of;
В коде Box2D большую часть занимает constraint solver ("решальщик" ограничений). Задача Constraint solver просчёт ограничений для правильного поведения тел при столкновениях. При просчёте одного ограничения не возникает особых трудностей. Однако при просчете нескольких ограничений, разрешение одного ограничения слегка нарушает остальные. Поэтому для получения хорошего результата необходимо произвести просчет всех ограничений несколько раз (т.е. сделать несколько итераций). В Box2d мы предлагаем использовать 10 итераций. Вы можете задать количество итераций по своему усмотрению, но необходимо помнить следующее правило «чем больше количество итераций, тем больше точность и меньше скорость просчёта ограничений» и наоборот «чем меньше количество итераций, тем меньше точность и больше скорость». Задаем количество итераций:
int32 iterations = 10;
Заметьте, что timeStep и количество итераций никак не связаны между собой. Итерация это НЕ под-шаг! Одна итерация это один расчет всех ограничений в каждый момент
времени. Мы можем использовать несколько проходов в каждый момент времени для увеличения точности.
Теперь мы готовы начать цикл моделирования. В вашей игре цикл моделирования может быть объединён с игровым циклом. В таком случае на каждой итерации игрового цикла необходимо вызывать b2World::Step. Обычно достаточно одного вызова, но это зависит от частоты кадров и величины timeStep.
Так как программа Hello World разработана в максимально упрощенном виде, она не имеет графической части. Чтобы не быть слишком скучным код выводит позицию и угол поворота динамичного тела. Ура! У нас есть цикл, который моделирует поведение динамичного тела на протяжении 60 временных отрезков, суммарное время моделирования равно 1 секунде.
for (int32 i = 0; i < 60; ++i)
{
world.Step(timeStep, iterations);
b2Vec2 position = body->GetPosition();
float32 angle = body->GetAngle();
printf("%4.2f %4.2f %4.2f\n", position.x, position.y, angle); }
2.5. Сбор мусора
Когда объект мира покидает область видимости или уничтожается вследствие удаления указателя на него, вся память зарезервированная миром для тел и соединений между ними освобождается. Таким образом, вы будете должны обнулить указатели на все тела, фигуры и соединения которые хранятся в вашей игре, т.к. эти указатели станут недействительными.