0
votes

Really a basic question, but I am moving a sprite A with a physics body over another kind of sprites B having another physics body. I expect the collision callback oncontact to be called for these bodies. They have their respective category bitmasks set using setCategoryBitmask() and also respectively have each other's categories set using setContactTestBitmask().

The collision works as long as I do not move sprite A. I assume the problem is that I move sprite A using cocos2d actions, and I need to do something else. But using cocos2d actions for scripting things like these look so much simpler to me than anything else I can think of.

  • Move sprite A using physics calls. (looks like a lot of work, and it looks like it's hard to achieve exact scripting perfection)
  • Do my own collision detection in update() instead. (looks like a bunch of work too, especially if the sprites are rotated etc)

Is there any other shortcut? Or did I miss something else?

2

2 Answers

0
votes

I ended up doing "Do my own collision detection in update() instead". It wasn't too problematic.

Something like this in update()...

const Rect RECT_A = spriteA->getBoundingBox();
for (auto spriteB : someparent->getChildren()) {
    const Rect RECT_B = spriteB->getBoundingBox();
    if (RECT_A.intersectsRect(RECT_B)) {
         // Hit
    }
}
0
votes

Contaction detection should be fine while collion doesn't work.

Scene* HelloWorld::createScene()
{
    // 'scene' is an autorelease object
    auto scene = Scene::createWithPhysics();

    // 'layer' is an autorelease object
    auto layer = HelloWorld::create();

    // add layer as a child to scene
    scene->addChild(layer);

    scene->getPhysicsWorld()->setDebugDrawMask(PhysicsWorld::DEBUGDRAW_ALL);
    scene->getPhysicsWorld()->setGravity(Vec2::ZERO);

    // return the scene
    return scene;
}

bool HelloWorld::init()
{
   if ( !Layer::init() )
    {
        return false;
    }

    auto createSprite = [this](const Vec2& pos) {
        auto sprite = Sprite::create();
        auto bodyA = PhysicsBody::createCircle(20);
        sprite->setPhysicsBody(bodyA);
        sprite->setPosition(pos);

        bodyA->setCollisionBitmask(0xff);
        bodyA->setCategoryBitmask(0xff);
        bodyA->setContactTestBitmask(0xff);

        return sprite;
    };

    auto spriteA = createSprite(Vec2(300, 300));
    auto moveBy = MoveBy::create(1.f, Vec2(200, 200));
    spriteA->runAction(moveBy);

    auto spriteB = createSprite(Vec2(350, 350));

    addChild(spriteA);
    addChild(spriteB);

    auto contactListener = EventListenerPhysicsContact::create();
    contactListener->onContactBegin = [=](PhysicsContact& contact) {
        auto a = contact.getShapeA()->getBody()->getNode();
        auto b = contact.getShapeB()->getBody()->getNode();

        assert((a == spriteA && b == spriteB) || (a == spriteB && b == spriteA));

        log("It is working");

        return false;
    };

    _eventDispatcher->addEventListenerWithSceneGraphPriority(contactListener, this);

    return true;
}