I've been trying to prevent the collision between the Player and a VisionZone (a cone in front of the player that represent a flash light effect). The VisionZone is spawning on top of the player.
My problem is : since they both have physic bodies, they collide and the VisionZone pushes the player. This is not what I want.
The VisionZone and the Player have the same entity_collision_bitmask
, I thought this would actually prevent them from colliding in the begining ?
Since it didn't work, I tried using a CollisionManager, but I'm never getting into the OnContactBegin callback. The Init()
method is called in the init()
method of the scene and I call this line :
_eventDispatcher->addEventListenerWithSceneGraphPriority(CollisionManager::GetContactListener(), this);
CollisionManager.cpp
EventListenerPhysicsContact *CollisionManager::m_contactListener = nullptr;
void CollisionManager::Init() {
m_contactListener = EventListenerPhysicsContact::create();
m_contactListener->onContactBegin = [](PhysicsContact &contact) { return ContactBeginCallback(contact); };
m_contactListener->onContactSeparate = [](PhysicsContact &contact) { return ContactSeparateCallback(contact); };
}
bool CollisionManager::ContactBeginCallback(PhysicsContact &contact) {
PhysicsBody *_bodyA = contact.getShapeA()->getBody();
PhysicsBody *_bodyB = contact.getShapeB()->getBody();
const bool visionAndWallCondition = ((_bodyA->getCategoryBitmask() == vision_zone_collision_bitmask &&
_bodyB->getCategoryBitmask() == map_collision_bitmask) ||
(_bodyB->getCategoryBitmask() == vision_zone_collision_bitmask &&
_bodyA->getCategoryBitmask() == map_collision_bitmask));
if (visionAndWallCondition) {
for (Vec2 _p: contact.getContactData()->points) VisionZone::sm_shapeCollisionPoints.push_back(_p);
return true;
}
return false;
}
bool CollisionManager::ContactSeparateCallback(PhysicsContact &contact) {
PhysicsBody *_bodyA = contact.getShapeA()->getBody();
PhysicsBody *_bodyB = contact.getShapeB()->getBody();
const bool visionAndWallCondition = ((_bodyA->getCategoryBitmask() == vision_zone_collision_bitmask &&
_bodyB->getCategoryBitmask() == map_collision_bitmask) ||
(_bodyB->getCategoryBitmask() == vision_zone_collision_bitmask &&
_bodyA->getCategoryBitmask() == map_collision_bitmask));
if (visionAndWallCondition) {
VisionZone::sm_shapeCollisionPoints.clear();
return true;
}
return false;
}
NB : For the map_collision_bitmask
, it will be added to the walls physicBodies so the VisionZone collides with them, using Ray Tracing.
VisionZone.cpp
void VisionZone::CreateNewPhysicBody(std::vector<Vec2> &points) {
points.push_back(m_origin);
PhysicsBody *_body = PhysicsBody::createEdgePolygon(
&points.front(),
int(points.size()),
PHYSICSBODY_MATERIAL_DEFAULT,
1
);
_body->setCategoryBitmask(entity_collision_bitmask);
_body->setCollisionBitmask(map_collision_bitmask);
_body->setContactTestBitmask(contact_test_bitmask);
_body->setDynamic(true);
_body->setGravityEnable(false);
setPhysicsBody(_body);
}
Bitmasks.h
constexpr int vision_zone_collision_bitmask = 0x01;
constexpr int map_collision_bitmask = 0x02;
constexpr int entity_collision_bitmask = 0x03;
constexpr int contact_test_bitmask = 0x04;