0

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;
Thomas
  • 1
  • Update : The problem was that the two shapes were actually overlaping on spawn since they were spawning at the same spot. As the "onContactBegin" suggest, it is only triggered when two spaced shapes enter in collision ... I'm not sure if it is acutally intended but it is how it is – Thomas Jan 25 '23 at 17:19

0 Answers0