如何使SKSpriteNode仅对某些碰撞做出反应

时间:2014-01-18 17:39:12

标签: sprite-kit skspritenode skphysicsbody

在这个项目中有两名球员,两人都可以投篮。当相反的球员子弹击中一艘船时,它会降低他们的健康并消失,这很好。问题是我不希望船只或子弹反应相互碰撞。

以下是制作第一位玩家的代码:

player = [SKSpriteNode spriteNodeWithImageNamed:filePath];
    player.size = CGSizeMake(100, 100);
    player.position = CGPointMake(150, 250);
    player.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:player.size];
    player.physicsBody.categoryBitMask = playerCategory;
    player.physicsBody.collisionBitMask = wallCategory;
    player.physicsBody.friction = 1.0f;
    player.physicsBody.restitution = 1.0f;
    player.physicsBody.linearDamping = 1.0f;
    player.physicsBody.allowsRotation = NO;
    [self addChild:player];

第二名球员:

playerTwo = [SKSpriteNode spriteNodeWithImageNamed:filePath];
        playerTwo.size = CGSizeMake(100, 100);
        playerTwo.position = CGPointMake((384*2)-150, (512*2)-250);
        playerTwo.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:playerTwo.size];
        playerTwo.physicsBody.categoryBitMask = playerTwoCategory;
        playerTwo.physicsBody.collisionBitMask = wallCategory;
        playerTwo.physicsBody.friction = 1.0f;
        playerTwo.physicsBody.restitution = 1.0f;
        playerTwo.physicsBody.linearDamping = 1.0f;
        playerTwo.physicsBody.allowsRotation = NO;
        [self addChild:playerTwo];

初始化类别:

static const uint32_t playerCategory = 2;
static const uint32_t playerTwoCategory =   5;
static const uint32_t wallCategory =   1;
static const uint32_t bulletCategory =   4;
static const uint32_t bulletTwoCategory =   7;

为玩家一制造子弹:

    SKSpriteNode * bullet = [SKSpriteNode spriteNodeWithColor:[UIColor whiteColor]     size:CGSizeMake(5, 5)];
    bullet.position =  [gunOne convertPoint:CGPointMake(0,0) toNode:self];
    [self addChild:bullet];
    bullet.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:bullet.frame.size];
    bullet.physicsBody.categoryBitMask = bulletCategory;
    bullet.physicsBody.dynamic = YES;
    bullet.physicsBody.contactTestBitMask = playerTwoCategory | wallCategory;
    bullet.physicsBody.collisionBitMask = wallCategory;
    bullet.physicsBody.usesPreciseCollisionDetection = YES;

为玩家二制造子弹:

    SKSpriteNode * bulletTwo = [SKSpriteNode spriteNodeWithColor:[UIColor whiteColor] size:CGSizeMake(5, 5)];
    bulletTwo.position =  [gunOneTwo convertPoint:CGPointMake(0,0) toNode:self];
    [self addChild:bulletTwo];
    bulletTwo.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:bulletTwo.frame.size];
    bulletTwo.physicsBody.categoryBitMask = bulletTwoCategory;
    bulletTwo.physicsBody.dynamic = YES;
    bulletTwo.physicsBody.contactTestBitMask = playerCategory | wallCategory;
    bulletTwo.physicsBody.collisionBitMask = wallCategory;
    bulletTwo.physicsBody.usesPreciseCollisionDetection = YES;

这样做是否有任何明显的问题会导致第一个玩家和子弹对碰撞作出反应?在此先感谢您的帮助,并为长时间的阅读感到抱歉。

2 个答案:

答案 0 :(得分:0)

'static const uint32_t'是问题所在,它们实际上是对类别的顺序进行统计,而你必须做的是对船只进行相同数量的评估,然后高出子弹,这也必须是相同的数字。要在didBeginContact中区分它们,请为每个名称添加一个名称并使用它。

答案 1 :(得分:0)

我会像这样定义位和掩码:

#define BIT_WALL        (0x01 << 0)   // 0000 0001
#define BIT_PLAYER_1    (0x01 << 1)   // 0000 0010
#define BIT_PLAYER_2    (0x01 << 2)   // 0000 0100
#define BIT_BULLET_1    (0x01 << 3)   // 0000 1000
#define BIT_BULLET_2    (0x01 << 4)   // 0001 0000

// Just Bit groups for players and bullets
#define MASK_PLAYERS    (BIT_PLAYER_1 | BIT_PLAYER_2)  // 0000 0110
#define MASK_BULLETS    (BIT_BULLET_1 | BIT_BULLET_2)  // 0001 1000

// Players and bullets collide with wall, but not with each other
#define COLLISION_MASK_WALL       (MASK_PLAYERS | MASK_BULLETS) 
#define COLLISION_MASK_PLAYER_1   (BIT_WALL)
#define COLLISION_MASK_PLAYER_2   (BIT_WALL)
#define COLLISION_MASK_BULLET_1   (BIT_WALL)
#define COLLISION_MASK_BULLET_2   (BIT_WALL)

// Contact is detected if anything hits wall, or, if bullet1 hits player2 (and vice versa)
#define CONTACT_MASK_WALL         (MASK_PLAYERS | MASK_BULLETS)
#define CONTACT_MASK_PLAYER_1     (BIT_WALL | BIT_BULLET_2)
#define CONTACT_MASK_PLAYER_2     (BIT_WALL | BIT_BULLET_1)
#define CONTACT_MASK_BULLET_1     (BIT_WALL | BIT_PLAYER_2)
#define CONTACT_MASK_BULLET_2     (BIT_WALL | BIT_PLAYER_1)


// Creating objects
{
    wall.physicsBody.categoryBitMask = BIT_WALL;
    wall.physicsBody.collisionBitMask = COLLISION_MASK_WALL;
    wall.physicsBody.contactTestBitMask = CONTACT_MASK_WALL;

    player1.physicsBody.categoryBitMask = BIT_PLAYER_1;
    player1.physicsBody.collisionBitMask = COLLISION_MASK_PLAYER_1;
    player1.physicsBody.contactTestBitMask = CONTACT_MASK_PLAYER_1;

    bullet1.physicsBody.categoryBitMask = BIT_BULLET_1;
    bullet1.physicsBody.collisionBitMask = COLLISION_MASK_BULLET_1;
    bullet1.physicsBody.contactTestBitMask = CONTACT_MASK_BULLET_1;

    player2.physicsBody.categoryBitMask = BIT_PLAYER_2;
    player2.physicsBody.collisionBitMask = COLLISION_MASK_PLAYER_2;
    player2.physicsBody.contactTestBitMask = CONTACT_MASK_PLAYER_2;

    bullet2.physicsBody.categoryBitMask = BIT_BULLET_2;
    bullet2.physicsBody.collisionBitMask = COLLISION_MASK_BULLET_2;
    bullet2.physicsBody.contactTestBitMask = CONTACT_MASK_BULLET_2;
}