Sprite Kit Node不检测碰撞而不是弹跳

时间:2013-12-01 19:45:45

标签: macos collision-detection sprite-kit bounce

关注RayWenderlich tutorial我遇到了一些问题,无法创建一个让子弹弹回的块。但最令人讨厌的事情是无法检测到子弹和砖块之间的碰撞。现在,子弹就像它不存在一样通过砖块。

这是子弹和砖的定义: 子弹:

    bullet = [SKSpriteNode spriteNodeWithColor:[SKColor greenColor] size:kBulletSize];
    bullet.name = kShipFiredBulletName;
    bullet.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:bullet.frame.size];
    bullet.physicsBody.dynamic = YES;
    bullet.physicsBody.restitution = 1.0;
    bullet.physicsBody.affectedByGravity = NO;
    bullet.physicsBody.categoryBitMask = kShipFiredBulletCategory;
    bullet.physicsBody.contactTestBitMask = kInvaderCategory;
    bullet.physicsBody.collisionBitMask = 0x0;

砖:

SKNode* rebote;

rebote = [SKSpriteNode spriteNodeWithColor:[SKColor orangeColor] size:kBouncetSize];
rebote.position = CGPointMake(550, 500);
rebote.name = @"kBounceBlock";
rebote.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:rebote.frame.size];
rebote.physicsBody.restitution = 1.0;
rebote.physicsBody.friction = 0.0;
rebote.physicsBody.dynamic = NO;
rebote.physicsBody.affectedByGravity = YES;
rebote.physicsBody.categoryBitMask = kShipFiredBulletCategory;
rebote.physicsBody.contactTestBitMask = kInvaderCategory;
rebote.physicsBody.collisionBitMask = 0x0;

[self addChild:rebote];

这里是碰撞检测方法:

-(void)handleContact:(SKPhysicsContact*)contact
{
    // Ensure you haven't already handled this contact and removed its nodes
    if (!contact.bodyA.node.parent || !contact.bodyB.node.parent)
        return;

    NSArray* nodeNames = @[contact.bodyA.node.name, contact.bodyB.node.name];
    if ([nodeNames containsObject:kShipName] && [nodeNames containsObject:kInvaderFiredBulletName])
    {
        // Invader bullet hit a ship
        [self runAction:[SKAction playSoundFileNamed:@"ShipHit.wav" waitForCompletion:NO]];
        //1
        [self adjustShipHealthBy:-0.334f];

        if (self.shipHealth <= 0.0f)
        {
            //2
            [contact.bodyA.node removeFromParent];
            [contact.bodyB.node removeFromParent];
        }
        else
        {
            //3
            SKNode* ship = [self childNodeWithName:kShipName];
            ship.alpha = self.shipHealth;

            if (contact.bodyA.node == ship)
                [contact.bodyB.node removeFromParent];
            else
                [contact.bodyA.node removeFromParent];
        }
    }
    else if ([nodeNames containsObject:kInvaderName] && [nodeNames containsObject:kShipFiredBulletName])
    {
         NSLog(@"Contacto entre bala e Invader.");

        // Ship bullet hit an invader
        [self runAction:[SKAction playSoundFileNamed:@"InvaderHit.wav" waitForCompletion:NO]];
        [contact.bodyA.node removeFromParent];
        [contact.bodyB.node removeFromParent];
        //4
        [self adjustScoreBy:100];
    }

    if ([nodeNames containsObject:@"kBounceBlock"])
        NSLog(@"Contacto entre el cuerpo naranja !!");
}

但是我做错了?我在子弹和砖块中定义了恢复属性。砖块不是动态的,两者都在相同的'collisionBitMask'中。

我很丢失。 提前致谢

2 个答案:

答案 0 :(得分:4)

contactTestBitMaskcollisionBitMask设置正确的BrickBullet

由于某些原因,您将collisionBitMask设置为0x0,这意味着该节点根本不会与任何对象发生冲突。

另外,您为categoryBitMask指定了错误的Brick(与Bullet相同)。您应该为它创建一个单独的类别:

bullet.physicsBody.categoryBitMask = kShipFiredBulletCategory;
bullet.physicsBody.contactTestBitMask = kBrickCategory;
bullet.physicsBody.collisionBitMask = kBrickCategory;


rebote.physicsBody.categoryBitMask = kBrickCategory;
rebote.physicsBody.contactTestBitMask = kShipFiredBulletCategory;
rebote.physicsBody.collisionBitMask = kShipFiredBulletCategory;

答案 1 :(得分:2)

categoryBitMask是指定节点“所属”的类别(或类别)的位置。 contactTestBitMask是让节点知道在与它们发生碰撞时应该触发-handleContact:的其他节点的地方。

您将两个节点都放在contactTestBitMask kInvaderCategory之上。这意味着如果这些节点中的任何一个与categoryBitMask kInvaderCategory的节点发生冲突,则会调用其-handleContact:方法。但是,您的节点都没有categoryBitMask kInvaderCategory,因此永远不会发生。

例如,如果您要为rebote节点contactTestBitMask kShipFiredBulletCategory提供-handleContact:,那么每当bullet节点发生碰撞时,它都会调用bullet使用它,因为categoryBitMask节点的kShipFiredBulletCategory为{{1}}。