ContactListener
. Вот только примеры, которые я использовал, были не совсем верно выбраны. В Box2D есть намного более удобные средства для фильтрации столкновений, а именно – фильтры. О них и напишу в этот раз.
Фильтры обрабатываются перед обработкой коллизий. То есть, если на уровне фильтров мы укажем, чтобы какие-то объекты не сталкивались, то в дальнейшем обработки коллизий между этими объектами не будет. В случае же с использование ContactListener
, не будут срабатывать его методы для таких объектов. Оптимизация на лицо. А теперь поподробнее рассмотрим.
Категории и маски
Категории и маски – самый мощный способ для фильтрования столкновений, но также и самым сложный (для новичков). Идея состоит в том, чтобы определить категорию для типов объектов, и использовать маски для фильтрования столкновений между этими типами объектов. Для начала определим категории.
// 0000000000000001 in binary final public static short CATEGORY_PLAYER = 0x0001; // 0000000000000010 in binary final public static short CATEGORY_BALOOM = 0x0002; // 0000000000000100 in binary final public static short CATEGORY_RUNNER = 0x0004; // 0000000000001000 in binary final public static short CATEGORY_SCENERY = 0x0008;
Затем зададим их нашим объектам.
//игроку f.categoryBits = MyWorld.CATEGORY_PLAYER; //блокам и платформе f.categoryBits = MyWorld.CATEGORY_SCENERY; //для Baloom'а f.categoryBits = MyWorld.CATEGORY_BALOOM; //для Runner'а f.categoryBits = MyWorld.CATEGORY_RUNNER;
Вы должны были заметить, что нумерация 0×001, 0×002, 0×004 и 0×008. Почему? Дело в том, что категории и маски – битовые поля (закодированы в 16 битах). Это означает, что возможные категории являются степенью 2 (в десятичной системе счисления: 1, 2, 4, 8, 16, 32, 64, 128 …, или в шестнадцатеричном: 0×1, 0×2, 0×4, 0×8, 0×10, 0×20, 0×40, 0×80 …). 16 битов означают, что есть 16 возможных категорий от 0×0001 до 0×8000.
Теперь определим маски.
final public static short MASK_PLAYER = CATEGORY_RUNNER | CATEGORY_SCENERY; // или ~MASK_PLAYER final public static short MASK_BALOOM = CATEGORY_SCENERY ; final public static short MASK_RUNNER = CATEGORY_PLAYER | CATEGORY_SCENERY ; final public static short MASK_SCENERY = -1;
Обычная булева алгебра с типичными операциями над числами. Стоит лишь остановиться на маске и категории для пейзажных объектов. Почему -1? -1 означает, что объект будет контактировать со всеми другими объектами. Если же надо, чтобы объект не контактировал ни с кем, то установите значение 0.
Затем маски зададим нашим объектам.
//игроку f.maskBits = MyWorld.MASK_PLAYER; //блокам и платформе f.maskBits = MyWorld.MASK_SCENERY; //для Baloom'а f.maskBits = MyWorld.MASK_BALOOM; //для Runner'а f.maskBits = MyWorld.MASK_RUNNER;
Если кто-то не понял, по маскам и категориям куски из кода представлены. Целиком назначения фильтра приведу на всякий случай, как пример для игрока:
Filter f = new Filter(); f.categoryBits = MyWorld.CATEGORY_PLAYER; f.maskBits = MyWorld.MASK_PLAYER; playerSensorFixture.setFilterData(f); playerPhysicsFixture.setFilterData(f);
В итоге игрок будет взаимодействовать только с пейзажными объектами и с Runner’ом. Ballom только с пейзажем. Runner с игроком и пейзажем.
Фильтрация на уровне групп
Вы можете работать с категориями и масками, но порой нет необходимости их использовать, считать битовые маски и т.д. Группы специально были придуманы, чтобы отключить/включить обработку коллизий для каких-то связанных объектов.
Для начала, добавим ещё одного игрока.
BodyDef def2 = new BodyDef(); def.type = BodyType.DynamicBody; Body boxP2 = world.createBody(def2); player2 = new Player(boxP2); player2.getBody().setTransform(5.0f, 1.0f, 0); player2.getBody().setFixedRotation(true);
В классе Player
зададим группу.
Filter f = new Filter(); f.groupIndex = -1; playerSensorFixture.setFilterData(f); playerPhysicsFixture.setFilterData(f);
Так же необходимо задать группы для всех остальных объектов. Пускай для платформы groupIndex будет 3, а для блоков 2. В принципе, платформе и блокам можно группу не назначать, тогда будет установлено значение по умолчанию – 0. Теперь, если запустить игру, персонаж будет контактировать со всеми объектами кроме других персонажей.
Вы должны были обратить внимание на то, что индекс имеет отрицательное значение. Если индекс положителен — объекты всегда контактируют, если отрицателен — никогда не контактируют.
Исходники
Можете скачать исходники отсюда.
ссылка на оригинал статьи http://habrahabr.ru/post/163885/
Добавить комментарий