如何在 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;
}
我正在按照一些教程制作 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;
}