
Делаем конвейер в Box2D - туториал
Добрый вечер, друзья. Сегодня, как и обещал, я хочу рассказать как делать логический конвейер в Box2D 2.1a.
Для начала обрисуем что же такое «логический конвейер». Этот термин, я придумал вчера.
Для его реализации нам не требуется большое количество тел и джоинтов, как для «физического», хватит и одного.

Alert: Тутор довольно увесистый.
Оба имеют свои плюсы и минусы, каким пользоваться — зависит от ситуации.
Физический:
Красиво, реалистично провисает.
ресурсоёмко, если у вас много физ. объектов, то такой конвейер всё убьет.
голючит при натяжении, может сломаться.
Логический:
быстро работает, не требует много ресурсов на эмуляцию.
настраиваемый, можно сделать даже несколько областей разной скорости и направления на одном.
не ломается.
не так реалистично.
Да, вопрос красоты/производительности стар как мир. Тут нет однозначного вывода «какой лучше», это все равно, что сравнивать яхту и пароход. Если у вас игра построена на конвейерах (как на первом скрине, ссылка в конце статьи), тогда стоит выбирать первый вариант, если тр будет всего-лишь элементом мира, тогда, наверное, не стоит перенапрягать движок, особенно, если у вас и так не мало физ. тел.физ. тел.
Каждый раз, когда сталкиваются два тела, трение заставляет их скорости сравняться. Результат зависит от веса тел, их скорости и площади поверхности. Этот метод эмулирует движение одного/обоих контактирующих тел, а всё остальное ложится на плечи физическому движку. Можете представить это как будто там конвейер (так логичнее), или одно их тел действительно движется, а второе на нём лежит.
Кстати, сначала я думал применять импульс к точку прикосновения, но ничего хорошего их этого не вышло.
Это затронет такие классы:
Box2D\Dynamics\Contacts\b2Contact.as
Box2D\Dynamics\Contacts\b2ContactConstraint.as
Box2D\Dynamics\Contacts\b2ContactSolver.as
Итак, в b2Contact.as нужно добавить новое свойство surfaceVelocityModifier и его сеттер.
А так же занулять его на каждом update.
Открываем b2ContactConstraint.as и добавляем переменную surfaceVelocityModifier:
Теперь будем потрошить b2ContactSolver.as. Добавим присвоение в ф-цию Initialize()
И пересчёт скорости в ф-цию SolveVelocityConstraints()
Чтобы потешить себя чувством достижения, можно немного переделать стандартный breakable-тестбед:
Для начала обрисуем что же такое «логический конвейер». Этот термин, я придумал вчера.
Для его реализации нам не требуется большое количество тел и джоинтов, как для «физического», хватит и одного.

Alert: Тутор довольно увесистый.
Оба имеют свои плюсы и минусы, каким пользоваться — зависит от ситуации.
Физический:



Логический:




Да, вопрос красоты/производительности стар как мир. Тут нет однозначного вывода «какой лучше», это все равно, что сравнивать яхту и пароход. Если у вас игра построена на конвейерах (как на первом скрине, ссылка в конце статьи), тогда стоит выбирать первый вариант, если тр будет всего-лишь элементом мира, тогда, наверное, не стоит перенапрягать движок, особенно, если у вас и так не мало физ. тел.физ. тел.
Теория — смело пропускайте, если не интересно.
Сам не люблю теорию, потому опишу как работает метод очень коротко.Каждый раз, когда сталкиваются два тела, трение заставляет их скорости сравняться. Результат зависит от веса тел, их скорости и площади поверхности. Этот метод эмулирует движение одного/обоих контактирующих тел, а всё остальное ложится на плечи физическому движку. Можете представить это как будто там конвейер (так логичнее), или одно их тел действительно движется, а второе на нём лежит.
Кстати, сначала я думал применять импульс к точку прикосновения, но ничего хорошего их этого не вышло.
Процесс пошёл — модифицируем код
Как сделать физический конвейер из revolute-джоинтов и динамических тел вы нуже няка уже знаете, потому сейчас мы будем делать логический. Стоит также предупредить, что в процессе, я буду вносить изменения в код движка… опять. *evil laugh*Это затронет такие классы:
Box2D\Dynamics\Contacts\b2Contact.as
Box2D\Dynamics\Contacts\b2ContactConstraint.as
Box2D\Dynamics\Contacts\b2ContactSolver.as
Итак, в b2Contact.as нужно добавить новое свойство surfaceVelocityModifier и его сеттер.
А так же занулять его на каждом update.
// Искусственная поверхностная скорость. (для одной итерации)
var surfaceVelocityModifier:Number = 0;
/** Изменяем относительную скорость двух "фикстур", перпендикулярную нормали контакта
* Работает только в текущей итерации, или суб-итерации для (bullet=true)
*/
public function SetTangentSpeed(Velocity:Number):void
{
surfaceVelocityModifier = Velocity;
}
... обрыв
b2internal function Update(listener:b2ContactListener) : void
{
surfaceVelocityModifier = 0;
... обрыв
Открываем b2ContactConstraint.as и добавляем переменную surfaceVelocityModifier:
public var manifold:b2Manifold; // существующий код
// Искусственная поверхностная скорость.
public var surfaceVelocityModifier:Number; //добавляемый код
Теперь будем потрошить b2ContactSolver.as. Добавим присвоение в ф-цию Initialize()
cc.type = manifold.m_type; // существующий код
cc.surfaceVelocityModifier = contact.surfaceVelocityModifier; //добавляемый код
И пересчёт скорости в ф-цию SolveVelocityConstraints()
dvX = vB.x - wB * ccp.rB.y - vA.x + wA * ccp.rA.y; // существующий код
dvY = vB.y + wB * ccp.rB.x - vA.y - wA * ccp.rA.x; // существующий код
// Вычисляем скорость с учётом нашего модификатора
dvX -= c.surfaceVelocityModifier * tangentX; //добавляемый код
dvY -= c.surfaceVelocityModifier * tangentY; //добавляемый код
Полпути — используем наработку
Чтобы потешить себя чувством достижения, можно немного переделать стандартный breakable-тестбед:
- +24
- MidnightOne
Комментарии (24)
www.iforce2d.net/b2dtut/conveyor-belts
Зато есть ссылка на источник какой-то там картинки, расстановка приоритетов, по-моему, страдает у тебя.
Да, это стоит сказать. Идея — mayobutter, зародилась здесь: www.box2d.org/forum/viewtopic.php?f=3&t=2861 Реализация моя.
Сходства со статьей по ссылке вижу, но он не является использованным материалом.
Заркуа, запостить картинку не сложно, а теперь, будь добр, сравни статьи.
А ты на пост картинки?
Сопоставимо?
Или может я скопировал все, как ты картинку?
Кстати, Claymore, в отличии от тебя, знает о чем говорит.
А ты продолжай постить картинки, пока другие делом занимаются.
Статью читал, делом занимаюсь (пощение картинок не особо время отнимает), написать такое же примерно могу, использовал бы переделанный вцк как уже писал постепенно. Могу и не использовать, просто дольше времени займет.
Дискуссию прекращаю
Миднайт, реально, хватит воспринимать гифки как троллинг, что ты такой чувствительный то? )
Имхо со стороны заркуа всё было корректно, в отл. от твоей…
2. Не только я считаю это троллингом.
3. Если это не троллинг, то какой смысл от таких «просто пикчей»?
Реализации различаются только способом хранения предельных углов, там через юзердату, у тебя добавлены дополнительные свойства в b2Fixture. Названия переменных тоже совпадают, именно это и натолкнуло на мысль, что именно это и есть оригинал алгоритма, который лег в основу написания статьи. Если алгоритм твой, то респект — молодец, но из-за такой степени схожести и различия дат публикаций, теоретически могут возникнуть недопонимания с Chris Campbell — iforce2d.net, исходники и так распространяются под лицензией zlib, которая разрешает делать с исходниками все, что заблагорассудится, кроме двух вещей:
— Запрещается утверждать, что это вы написали оригинальный продукт;
— Изменённые версии не должны выдаваться за оригинальный продукт;
Код поверхностной скорости давно входит в v2.3 box2d (правда, он выглядит по-другому и написан на другом языке), авторство мне не нужно.
Я не буду патентовать метод нахождения угла, который, хочу заметить, более надежен, чем предложенный iforce. Не буду, чтобы не возникало таких идиотских ситуаций с тем, кому он придет в голову независимо от меня.
Не понимаю некоторых товарищей, человек постарался, потратил свое личное время, а вместо адекватного обсуждения статьи в комментах какие-то картинки. Напишите лучше тоже что-нибудь полезное;)