Box2d - Изменение фильтра контактов на лету

Я использую cocos2d (iOS) и box2d для создания игры.
Я дошел до того, что мне нужно изменить контактный фильтр во время симуляции, и мне интересно, как это сделать.
Мне нужно использовать maskbits и categorybits , это нормально, я просто не знаю, как применить их к середине игры b2body.

Я думаю, мне может понадобиться получить исходный b2fixture или b2fixturedef b2body при инициализации, соответствующим образом изменить значения, а затем вызвать метод для обновления - world.Refilter()?

Это звучит несколько точно?

Любой совет, безусловно, приветствуется
Оливер.


person Ospho    schedule 06.06.2011    source источник


Ответы (3)


b2Filter filter;

for ( b2Fixture* f = body->GetFixtureList(); f; f = f->GetNext() ) {
    f->GetFilterData( &filter );
    filter.categoryBits = ...;
    filter.maskBits = ...;
    filter.groupIndex = ...;
    f->SetFilterData( &filter );
}

Очевидно, что это изменит настройки фильтра для всех приборов на теле — если вы хотите быть более избирательным, вам нужно будет каким-то образом определить, какой прибор является каким. Например. если вы знаете, что это единственное круговое приспособление, вы можете просто посмотреть на тип приспособления, чтобы принять решение, иначе вам придется использовать пользовательские данные приспособления, я думаю.

person iforce2d    schedule 07.06.2011

Вы можете перебрать все тела в b2World. На каждом теле вы можете перебрать его приспособление и изменить его фильтр. Для идентификации ваших тел вы можете использовать userData.

person Andrew    schedule 06.06.2011
comment
все мои b2body синтезированы из моего базового класса, так что я могу сделать: b2Fixture *fix = object.body->GetFixture()? - person Ospho; 07.06.2011
comment
@Oliver: вы можете взять список приборов, если у вас есть указатель на b2body - person Andrew; 07.06.2011

Ответ от iforce2d может быть устаревшим. Я получил следующий код, правильно работающий с box2d v2.2.1, cocos2D v2.0.0 с использованием Xcode v4.5.2 (здесь я предполагаю, что у меня есть указатель на b2Body с именем «тело» только с одним приспособлением, т. е. я не перебираю все крепления на кузове):

b2Fixture *fix = body->GetFixtureList();
b2Filter filter = fix->GetFilterData();   
filter.groupIndex = -1*kPlayerGroupIndex; 
fix->SetFilterData(filter);

В приведенном выше коде я предотвращаю столкновение 'body' с телом моего игрока, которое также имеет то же значение groupIndex, т. е. -1 * kPlayerGroupIndex, где kPlayerGroupIndex — положительная целочисленная константа. Любые тела с этим отрицательным индексом группы никогда не сталкиваются друг с другом. Вы также можете обновить categoryBits или maskBits соответственно, чтобы предотвратить коллизии.

GetFilterData(&filter) и SetFilterData(&filter) вернули мне ошибки, учитывая номера версий, которые я указал выше.

person DoctorE    schedule 23.07.2013