如何在 Cocos2d 中制作触发区域

How to make trigger area in Cocos2d

我正在按照一些教程制作 Flappy Bird 游戏。为了统计分数,我在分数区域中设置了PhysicsBody,但是在Unity中就像一个Rigibody,其他对象无法通过它。

大家可以参考https://www.youtube.com/watch?v=3zGTCGgwt_U&list=PLRtjMdoYXLf7GSD9crXIjMQiRuIZ7mUVp&index=12,就是我要的结果。我跟着它,但我不知道为什么会有所不同。

在我的情况下,分数线挡住了我的飞鸟。随着分数线和管道向后移动,我的飞扬小鸟被分数线推到屏幕边缘,游戏结束。

我想要 Unity 中的 Trigger Collider 之类的东西。 cocos2d有没有类似的东西?

同时在此处附上我的代码,它会生成管道和得分线:

void Pipe::Spawn(Layer* pipeLayer) {
    auto upperPipe = Sprite::create("pipe_upper.png");
    upperPipe->setAnchorPoint(Vec2(0.5,0));
    upperPipe->setScale(spriteScale);
    auto upperPipeBody = PhysicsBody::createBox(upperPipe->getContentSize());

    upperPipeBody->setDynamic(false);
    upperPipeBody->setCollisionBitmask(OBSTACLE_COLLISION_BITMASK);
    upperPipeBody->setContactTestBitmask(true);
    upperPipe->setPhysicsBody(upperPipeBody);

    auto bottomPipe = Sprite::create("pipe_bottom.png");
    bottomPipe->setAnchorPoint(Vec2(0.5,1));
    bottomPipe->setScale(spriteScale);

    auto bottomPipeBody = PhysicsBody::createBox(bottomPipe->getContentSize());
    bottomPipeBody->setDynamic(false);  
    bottomPipeBody->setCollisionBitmask(OBSTACLE_COLLISION_BITMASK);
    bottomPipeBody->setContactTestBitmask(true);
    bottomPipe->setPhysicsBody(bottomPipeBody);

    float randomPosIndex = CCRANDOM_0_1();
    if (randomPosIndex < PIPE_BOTTOM_THRESHOLD) {
        randomPosIndex = PIPE_BOTTOM_THRESHOLD;
    }
    else if (randomPosIndex > PIPE_UPPER_THRESHOLD) {
        randomPosIndex = PIPE_UPPER_THRESHOLD;
    }

    float gapHeight = Sprite::create("flappybird1_01.png")->getContentSize().height * spriteScale * PIPE_GAP_INDEX;

    Size visibleSize = Director::getInstance()->getVisibleSize();
    //setup bottom pipe
    bottomPipe->setPosition(Point(visibleSize.width, visibleSize.height * randomPosIndex));
    //setup upper pipe
    upperPipe->setPosition(Point(visibleSize.width, bottomPipe->getPositionY() + gapHeight));
    //setup score area
    auto scoreNode = Node::create();
    auto scoreNodeBody = PhysicsBody::createBox(Size(1, gapHeight));
    scoreNodeBody->setDynamic(false);
    scoreNodeBody->setCollisionBitmask(SCORE_COLLISION_BITMASK);
    scoreNodeBody->setContactTestBitmask(true);
    scoreNode->setPhysicsBody(scoreNodeBody);

    scoreNode->setPosition(Point(bottomPipe->getPositionX(), bottomPipe->getPositionY() + gapHeight / 2));

    auto bottomPipeAction = RepeatForever::create(MoveBy::create(1, Vec2(-PIPE_MOVE_SPEED, 0)));
    auto upperPipeAction = RepeatForever::create(MoveBy::create(1, Vec2(-PIPE_MOVE_SPEED, 0)));
    auto scoreNodeAction = RepeatForever::create(MoveBy::create(1, Vec2(-PIPE_MOVE_SPEED, 0)));
    bottomPipe->runAction(bottomPipeAction);
    upperPipe->runAction(upperPipeAction);
    scoreNode->runAction(scoreNodeAction);

    pipeLayer->addChild(bottomPipe);
    pipeLayer->addChild(upperPipe);
    pipeLayer->addChild(scoreNode);

    CCLOG("Spawn Pipe");
}

感谢 ryemoss 的参考资料。只需在碰撞回调函数中 return false 即可解决一切!

bool GameScene::onContactBegin(PhysicsContact &contact)
{
    PhysicsBody* a = contact.getShapeA()->getBody();
    PhysicsBody* b = contact.getShapeB()->getBody();

    if ( (a->getCollisionBitmask() == FLAPPYBIRD_COLLISION_BITMASK && b->getCollisionBitmask() == OBSTACLE_COLLISION_BITMASK) ||
        (b->getCollisionBitmask() == FLAPPYBIRD_COLLISION_BITMASK && a->getCollisionBitmask() == OBSTACLE_COLLISION_BITMASK)
        ) 
    {
        auto gameoverScene = GameOverScene::createScene();
        Director::getInstance()->replaceScene(TransitionFade::create(SCENE_TRANSITION_DURATION, gameoverScene));
    }
    else if ((a->getCollisionBitmask() == FLAPPYBIRD_COLLISION_BITMASK && b->getCollisionBitmask() == SCORE_COLLISION_BITMASK) ||
        (b->getCollisionBitmask() == FLAPPYBIRD_COLLISION_BITMASK && a->getCollisionBitmask() == SCORE_COLLISION_BITMASK)) 
    {
        score++;
        CCLOG("Score Count: %i", score);
        return false;
    }

    return true;
}