Как стать автором
Обновить

Физика на Flash. Box2D Engine

Время на прочтение4 мин
Количество просмотров11K

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

Ссылки


Сам проект Box2D находится по этому адресу — http://www.box2d.org/, там можно почитать о его возможностях, пообщаться на форуме и т.д.
С него был сделан AS3 порт, домашняя страница — http://box2dflash.sourceforge.net/. На ней выложен клип, показывающий возможности этого движка. Кстати, всех с пятницей )


Использование (самое базовое)


1. Создаём «мир», все расчёты происходят только в пределах этого мира, объект, выходящий за его границы, выпадает из расчётов. Так что делаем с запасом (WIDTH и HEIGHT — размеры окна):
      // world bounding box
      var worldAABB : b2AABB = new b2AABB();
      worldAABB.lowerBound.Set(-WIDTH, -HEIGHT);
      worldAABB.upperBound.Set(2*WIDTH, 2*HEIGHT);      
      
      // create world. zero gravity + use "sleeping" for objects
      m_world = new b2World(worldAABB, b2Vec2.Make(0, 0), true);


* This source code was highlighted with Source Code Highlighter.

2. Добавляем объект в мир.
Объект характеризуется двумя составляющими.
Первая — геометрическое представление объекта (его «поверхность»). Каждый объект может состоять из нескольких shape, которые представляют собой выпуклые многоугольники или окружности (но ничего не мешает расширить базовый shape и написать свой собственный).
Здесь же задаётся плотность, сила трения и т.д.
      // shape definition
      var bodyShapeDef : b2PolygonDef = new b2PolygonDef();
      // as rectangle
      bodyShapeDef.SetAsBox(w/2, h/2);
      // density
      bodyShapeDef.density = 1.0;
      // friction
      bodyShapeDef.friction = 0.3;


* This source code was highlighted with Source Code Highlighter.

Вторая — сам объект, его положение, масса, момент инерции и т.д.
Описание объекта:
      // object definition
      var bodyDef : b2BodyDef = new b2BodyDef();
      // world position
      bodyDef.position.Set(xc, yc);
      // linear "friction with world"
      bodyDef.linearDamping = 0.3;
      // angular "friction with world"
      bodyDef.angularDamping = 0.3;


* This source code was highlighted with Source Code Highlighter.

Создание объекта (он автоматически регистрируется в мире). Задание ему ранее созданного геометрического представления, и (очень удобно) автоматический расчёт всех физических параметров на основе его плотности и формы.
      // create object from definition
      var body : b2Body = m_world.CreateBody(bodyDef);
      // create object shape from shape definition
      body.CreateShape(bodyShapeDef);
      // calculate mass, center of mass and inertia
      // based on shape
      body.SetMassFromShapes();


* This source code was highlighted with Source Code Highlighter.

Есть ещё третья (необязательная) составляющая объекта — его представление на экране. На начальных этапах разработки можно воспользоваться классом b2DebugDraw, который показывает все объекты, связи между ними и т.д. Но как связать, к примеру собственный MovieClip и физический объект?
Самая часто используемая практика — воспользоваться полем userData созданного объекта.
Запоминаем экранное представление в этом поле:
      // save screen object in userData field
      body.SetUserData(bodyDisplayObject);

* This source code was highlighted with Source Code Highlighter.

3. Эмуляция
Тут всё просто. У мира есть функция Step, которая принимает время шага в миллисекундах секундах и кол-во итераций, которые надо проделать на этом шаге. После эмуляции проходим по всем объектам мира, смотрим, если поле userData содержит экранное представление — то обновляем положение/вращение этого представления в соответствии с полями физического объекта.
   // calculate physics
   // using 10 steps of physics for each frame
   m_world.Step(dt, 10);

   // loop for all physic objects
   for(var body : b2Body = m_world.GetBodyList(); body; body = body.GetNext())
   {
    // if userData is not a shape, then skip this object
    if(!(body.GetUserData() is Shape))
     continue;

    // update screen object to be equal physical object     
    body.GetUserData().x = body.GetPosition().x;
    body.GetUserData().y = body.GetPosition().y;
    body.GetUserData().rotation = body.GetAngle() * 180.0 / Math.PI;
   }


* This source code was highlighted with Source Code Highlighter.

Пример


Написал небольшое приложение в попытках создать змею. 80 прямоугольников связаны попарно RevoluteJoint'ами, с ограничением вращения в +-20 градусов. При движении мышкой головной сегмент змеи получает импульс в направлении курсора, в результате вся змея ползёт. Также в мире расставлены объекты, чтобы было вокруг чего ползать.
По клику приложение переключается между собственным рисованием и b2DebugDraw.
приложение — http://www.rexxar.ru/snake/
исходники — http://www.rexxar.ru/snake/src.zip

Ещё один тест — показывает точки соударений. По клику создаётся новый прямоугольник и падает на землю.
приложение — http://www.rexxar.ru/phys/.

Вывод


Разбор движка и написание примеров заняло буквально несколько часов, очень простой, удобный, быстрый и мощный инструмент для эмуляции физики. Буду использовать.
Теги:
Хабы:
+69
Комментарии40

Публикации

Изменить настройки темы

Истории

Ближайшие события

PG Bootcamp 2024
Дата16 апреля
Время09:30 – 21:00
Место
МинскОнлайн
EvaConf 2024
Дата16 апреля
Время11:00 – 16:00
Место
МоскваОнлайн
Weekend Offer в AliExpress
Дата20 – 21 апреля
Время10:00 – 20:00
Место
Онлайн