Cocos2d-x v3.0rc1 PhysicsBody联系问题

时间:2014-04-06 21:14:57

标签: android c++ ios cocos2d-x

遇到物理身体碰撞/接触不能按照我预期的方式工作的问题。我可能会误解他们应该如何工作。我的理解是,如果physicsBodyA的类别位掩码为0x1,而physicsBodyB的接触测试位掩码为0x1,则联系测试应评估为true,我应该从事件调度程序获得回调。

但是,这并不起作用。我得到联系评估为true的唯一方法是我还设置physicsBodyA的联系位掩码以匹配physicsBodyB的类别位掩码。基本上,类别和接触测试位掩码必须彼此镜像。在实践中它看起来像这样:

bool TestLayer::init() {

    // Call super init
    if (!Layer::init()) {
        return false;
    }

    // Get screen size
    Size visibleSize = Director::getInstance()->getVisibleSize();

    // Bitmasks
    int BITMASK_BOUNDARY = 0x1 << 0;
    int BITMASK_HERO = 0x1 << 1;

    // Boundary node
    Node *boundaryNode = Node::create();
    boundaryNode->setAnchorPoint(Point(0.5, 0.5));
    boundaryNode->setPosition(Point(visibleSize.width/2.0, visibleSize.height/2.0));

    // Physics body for boundary node
    PhysicsBody *boundaryBody = PhysicsBody::createEdgeBox(visibleSize);
    boundaryBody->setCategoryBitmask(BITMASK_BOUNDARY);
    boundaryBody->setContactTestBitmask(BITMASK_HERO);
    boundaryBody->setDynamic(false);

    // Set boundary body and add to scene
    boundaryNode->setPhysicsBody(boundaryBody);
    this->addChild(boundaryNode);

    // Hero node
    Sprite *hero = Sprite::create("hero_ship.png");
    hero->setPosition(Point(visibleSize.width/2.0, visibleSize.height - 30.0));

    // Physics body for hero node
    PhysicsBody *heroBody = PhysicsBody::createBox(hero->getContentSize());
    heroBody->setCategoryBitmask(BITMASK_HERO);

    // Set hero body and add to scene
    hero->setPhysicsBody(heroBody);
    this->addChild(hero);

    /*
     * NOTICE: If I don't set the contact test bitmask on my hero
     * body, the event listener onContactBegin callback will not
     * be called.
     */

    heroBody->setContactTestBitmask(BITMASK_BOUNDARY);

    // Create an event listener
    EventListenerPhysicsContact *listener = EventListenerPhysicsContact::create();

    // Use lambda for listener callback
    listener->onContactBegin = [](PhysicsContact &contact) {
        CCLOG("Physics contact began.");
        return true;
    };

    // Register listener with event dispatcher
    this->getEventDispatcher()->addEventListenerWithSceneGraphPriority(listener, this);

    // Everything worked out on init, return true
    return true;
}

1 个答案:

答案 0 :(得分:0)

来自Box2D手册:

--------引用

  

碰撞过滤可以防止灯具之间发生碰撞。   例如,假设您制作一个骑自行车的角色。你要   自行车与地形碰撞和角色碰撞   与地形,但你不希望角色碰撞   自行车(因为它们必须重叠)。 Box2D支持这种碰撞   使用类别和组进行过滤。 Box2D支持16次碰撞   类别。对于每个夹具,您可以指定它属于哪个类别   至。您还可以指定此夹具可能碰撞的其他类别   用。例如,您可以在多人游戏中指定所有   玩家不会相互碰撞,怪物也不会碰撞   彼此,但玩家和怪物应该相互碰撞。这是完成的   掩蔽位。例如:

playerFixtureDef.filter.categoryBits = 0x0002; 
monsterFixtureDef.filter.categoryBits = 0x0004; 
playerFixtureDef.filter.maskBits = 0x0004; 
monsterFixtureDef.filter.maskBits = 0x0002;
  

以下是发生碰撞的规则:

uint16 catA = fixtureA.filter.categoryBits; 
uint16 maskA = fixtureA.filter.maskBits; 
uint16 catB = fixtureB.filter.categoryBits; 
uint16 maskB = fixtureB.filter.maskBits;
if ((catA & maskB) != 0 && (catB & maskA) != 0) 
{
  // fixtures can collide
}

--------报价结束

所以最重要的是,如果你想让两件事在碰撞方面以相同的方式做出反应,那么它们必须具有相同的类别和掩码位。

对于更多(非常好的)深入讨论,请继续look at this site(不,这不是我的)。

对于其他一些有趣的Box2D内容,look here(这是我的)。