我的玩家以外的物理机构在碰撞时不会调用didBeginContact

时间:2014-04-02 00:06:11

标签: objective-c collision-detection sprite-kit

在我的游戏中,我有4个位掩码,所有东西都已设置好,但只有当第一个位掩码(playerCategory)与某些东西发生碰撞时才会调用didBeginContact。如果3与4发生碰撞,即使我设置了contactTestBitMask,也没有任何反应。

myscene.h

    self.physicsWorld.gravity = CGVectorMake(0.0, -2.45);
    self.physicsWorld.contactDelegate = self;

    self.player = [SKSpriteNode spriteNodeWithColor:[SKColor blueColor] size: CGSizeMake(10.0, 20.0)];
    self.player.position = CGPointMake(20.0, self.frame.size.height);
    self.player.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:self.player.size];
    self.player.physicsBody.affectedByGravity = YES;
    self.player.physicsBody.dynamic = YES;
    self.player.physicsBody.categoryBitMask = playerCategory;
    self.player.physicsBody.contactTestBitMask = enemyCategory;
    self.player.physicsBody.collisionBitMask = tileCategory;
    [self.gameNode addChild:self.player];

    [...]

- (void) swipeRightHandler:(UISwipeGestureRecognizer *) recognizer {
    NSLog(@"swipe right");
    SKSpriteNode *attackRect = [SKSpriteNode spriteNodeWithColor:[SKColor redColor] size:CGSizeMake(40, 5)];
    attackRect.position = CGPointMake(self.player.position.x + 10, self.player.position.y);
    attackRect.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:attackRect.size];
    attackRect.physicsBody.categoryBitMask = attackCategory;
    attackRect.physicsBody.contactTestBitMask = 255;
    attackRect.physicsBody.collisionBitMask = enemyCategory;
    attackRect.physicsBody.affectedByGravity = NO;
    attackRect.physicsBody.dynamic = NO;
    [self.gameNode addChild:attackRect];
    [attackRect runAction:[SKAction moveBy:CGVectorMake(250, 0) duration:1.0] completion:^{
        [attackRect removeFromParent];
    }];
}

RandomLevelGenerator.m:

        SKSpriteNode *enemy = [SKSpriteNode spriteNodeWithColor:[SKColor greenColor] size:CGSizeMake(20, 20)];
        enemy.position = CGPointMake(visual_x, FLOOR_X + arc4random_uniform(MAX_Y - FLOOR_X));
        enemy.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:enemy.size];
        enemy.physicsBody.categoryBitMask = enemyCategory;
        enemy.physicsBody.contactTestBitMask = playerCategory | attackCategory;
        enemy.physicsBody.collisionBitMask = attackCategory;
        enemy.physicsBody.affectedByGravity = NO;
        enemy.physicsBody.dynamic = NO;
        [self.scene.gameNode addChild:enemy];

LevelGenerator.h:

static const uint32_t playerCategory    =   0x1 << 0;
static const uint32_t tileCategory      =   0x1 << 1;
static const uint32_t enemyCategory     =   0x1 << 2;
static const uint32_t attackCategory    =   0x1 << 3;

MyScene.m:

SKPhysicsBody *firstBody, *secondBody;

if(contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask)
{
    firstBody = contact.bodyA;
    secondBody = contact.bodyB;
} else {
    firstBody = contact.bodyB;
    secondBody = contact.bodyA;
}
NSLog(@"%d - %d", firstBody.categoryBitMask, secondBody.categoryBitMask);

最后一个NSLog,只打印1 - x,而不是3 - x。我也试过允许其他碰撞,我不能让它们碰撞。

1 个答案:

答案 0 :(得分:2)

如果两个AND组合的categoryBitMask为零,则它们不会生成联系事件。例如,这发生在playerCategory(1)和enemyCategory(4)中:1 & 4 = 0&lt; ==玩家和敌人之间不会产生任何联系事件。在这种情况下,它甚至不会检查contactBitMask标志。

如果您希望两个实体生成联系事件,则它们都必须设置相同的类别位掩码标记。

categoryBitMask的默认值为0xFFFFFFFF,以便所有实体可以相互联系。 collisionBitMask也是如此,因为通常您希望所有实体默认联系并发生碰撞。

在大多数情况下,您真正​​需要修改的唯一位掩码是contactBitMask ,默认值为0,这意味着默认情况下不会生成任何联系事件(以提高性能)。

仅更改仅更改contactBitMask不足的其他位掩码。

例如,当您想要接触事件但没有碰撞反馈时(=当碰撞物体接触时速度/位置发生变化),请确保那些物体的collisionBitMask AND在一起为0.这样可以身体生成联系事件,但相互传递。用于创建触发器,即当玩家进入某个区域时,您可以让他通过但也会触发游戏事件。

或者当你想为两个不同类别的身体使用相同的联系人位掩码时,他们只应该与共享相同类别的其他身体发生碰撞/接触 - 即常规和“幽灵”角色应该与其他所有人有相同的联系行为在游戏中,除了他们不应该与他们的物质(非鬼)对应物接触/碰撞。在这种情况下,对两个实体使用相同的contactBitMaskcollisionBitMask。然后在categoryBitMask中为所有其他类别设置所有标志,但不要为表示物质和鬼体的两个类别设置标志。即如果物质类别为2且ghost类别为8,则categoryBitMask应为:0xFFFFFFFF - 2 - 8 = 0xFFFFFFF5(低8位将为:11110101)

长话短说:categoryBitMask标志应该从0xFFFFFFFF清除(而不是设置为特定位),以便特定类别的个别机构不会相互联系但仍然与所有人联系其他机构。