Я пытаюсь проверить наличие определенных столкновений между спрайтами с физическими телами. Проблема в том, что я не знаю, как назначить тег для каждого физического тела узла или правильно установить битовую маску для каждого спрайта. Я успешно проверяю наличие столкновений, но это только true или false для всех объектов.
Я следую руководству в документации по cocos2d-x, которое я связал ниже. В нем объясняется, как установить биты маскирования и категории маскирования.
Фильтрация столкновений позволяет предотвратить столкновения между фигурами. Cocos2d-x> поддерживает фильтрацию коллизий, используя битовые маски категорий и групп.
Cocos2d-x поддерживает 32 категории столкновений. Для каждой фигуры вы можете указать, к какой категории она относится. Вы также указываете, с какими другими категориями может сталкиваться эта форма. Это сделано с битами маскировки
Проблема в том, что когда я установил:
sprite1->getPhysicsBody()->setCategoryBitmask(0x02); // 0010
sprite1->getPhysicsBody()->setCollisionBitmask(0x01); // 0001
Там не обнаружение столкновений для этих спрайтов. Но когда я установил:
invaderPhysicsBody->setContactTestBitmask(true);
Там является обнаружение столкновения.
Кто-нибудь знает, как успешно установить битовую маску коллизии или битовую маску категории?
Объекты с возможными столкновениями:
Это моя функция onContactBegin, которая удалит Node после их столкновения. Здесь я должен проверить, какие объекты столкнулись.
bool Gameplay::onContactBegin(PhysicsContact &contact) {
std::cout << "onContactBegin -------> " << std::endl;
player_score += 10;
auto nodeA = contact.getShapeA()->getBody()->getNode();
auto nodeB = contact.getShapeB()->getBody()->getNode();
std::cout << contact.getShapeA()->getTag() << std::endl;
if ((contact.getShapeA()->getCategoryBitmask() & contact.getShapeB()->getCollisionBitmask()) == 0
|| (contact.getShapeB()->getCategoryBitmask() & contact.getShapeA()->getCollisionBitmask()) == 0)
{
std::cout << "Overlap!" << std::endl;
}
nodeA->removeFromParent();
nodeB->removeFromParent();
return true;
}
Вот мой слушатель столкновений:
// Enable collision listener.
auto contactListener = EventListenerPhysicsContact::create();
contactListener->onContactBegin = CC_CALLBACK_1(Gameplay::onContactBegin, this);
this->getEventDispatcher()->addEventListenerWithSceneGraphPriority(contactListener, this);
Вот как я сейчас создаю и устанавливаю физические тела для своих спрайтов:
int spacing = 0;
// Four Player Shields
for (int i = 0; i < 4; i++) {auto shield = Sprite::create("player_shield.png");
auto shield_x = shield->getContentSize();
auto shield_y = shield->getContentSize();
auto shieldPhysicsBody = PhysicsBody::createBox(Size(shield_x.width,shield_y.height), PHYSICSBODY_MATERIAL_DEFAULT);
shieldPhysicsBody->setContactTestBitmask(true);
shieldPhysicsBody->setDynamic(true);
shieldPhysicsBody->setTag(0);
shield->setPosition(Vec2(200 + spacing, 150));
shield->addComponent(shieldPhysicsBody);
this->addChild(shield);
spacing += 200;
}
В вашем коде есть большая ошибка. setContactTestBitmask
принять int
скорее, чем bool
, Когда вы звоните shieldPhysicsBody->setContactTestBitmask(true)
это на самом деле shieldPhysicsBody->setContactTestBitmask(0x0000001)
, А также 0x000001 & 0x000010 = 0
так что никакое контактное событие не будет инициировано. &
Результат categoryBitmask для spriteA и ContactTestBitmask для spriteB определяет, будет ли вызвано событие контакта. Кстати, вообще говоря, вам не нужно проверять контакт вручную, то есть:
if ((contact.getShapeA()->getCategoryBitmask() & contact.getShapeB()->getCollisionBitmask()) == 0
|| (contact.getShapeB()->getCategoryBitmask() & contact.getShapeA()->getCollisionBitmask()) == 0)
{
std::cout << "Overlap!" << std::endl;
}
Других решений пока нет …