SKPhysicsContact有什么方法可以确定哪个体是A和B?

时间:2016-11-05 08:38:21

标签: objective-c swift sprite-kit game-physics

在SpriteKit中我们检测到了didBeginContact方法。 但做这样的事情看起来有点愚蠢: func didBeginContact(联系人:SKPhysicsContact){

    if let contactA = contact.bodyA.node?.name {

        if let contactB = contact.bodyB.node?.name {

            //now that we have safely unwrapped these nodes, we can operate on them

            if contactA == "ball" {

                collisionBetweenBall(contact.bodyA.node!, object: contact.bodyB.node!)

            } else if contactB == "ball" {

                collisionBetweenBall(contact.bodyB.node!, object: contact.bodyA.node!)

            }

        }

    }

}

有什么方法可以确保bodyA始终是一个球?有没有与categorybitmask相关的规则?

2 个答案:

答案 0 :(得分:5)

如果您使用简单类别,每个物理主体只属于一个类别,则didBeginContact的这种替代形式可能更具可读性:

func didBeginContact(contact: SKPhysicsContact) {
    let contactMask = contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask

switch contactMask {

   case categoryBitMask.ball | categoryBitMask.something:
       print("Collision between ball and something")
       let ballNode = contact.bodyA.categoryBitMask == categoryBitMask.ball ? contact.bodyA.node! : contact.bodyB.node!
       ballNode.pop()
       score += 10

   default :
       //Some other contact has occurred
       print("Some other contact")
   }
}

请注意,如果您的类别更复杂,那么这不会起作用,因为简单的AND测试(categoryBitMask.ball | categoryBitMask.something)不会匹配。

答案 1 :(得分:0)

通常你会这样做

首先,如果你没有这样做,你会存储你的位掩码类别。

enum PhysicsCategory {
     static let ball: UInt32 =  0x1 << 0
     static let wall: UInt32 =  0x1 << 1
     static let enemy: UInt32 = 0x1 << 2
}

并将它们分配给你的精灵

 ball.physicsBody?.categoryBitMask = PhysicsCategory.ball
 ball.physicsBody?.contactTestBitMask = PhysicsCategory.wall | PhysicsCategory.enemy

 wall.physicsBody?.categoryBitMask = PhysicsCategory.wall
 wall.physicsBody?.contactTestBitMask = 0 

 enemy.physicsBody?.categoryBitMask = PhysicsCategory.enemy
 enemy.physicsBody?.contactTestBitMask = 0 

注意:因为球在这个例子中检查了与墙和敌人的接触,所以你不需要告诉墙或敌人用球检查接触。 它可以在1个物理体上完成,所以你可以在其他物体上将它设置为0,除非它们有其他特定的触点可供查找。

如果没有double if语句,你可以在联系方式中检查它们。

func didBegin(_ contact: SKPhysicsContact) {

    let firstBody: SKPhysicsBody
    let secondBody: SKPhysicsBody

    if contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask {
        firstBody = contact.bodyA
        secondBody = contact.bodyB
    } else {
        firstBody = contact.bodyB
        secondBody = contact.bodyA
    }


    // Ball hit wall or wall hit ball
    if (firstBody.categoryBitMask == PhysicsCategory.ball) && (secondBody.categoryBitMask == PhysicsCategory.wall) {

          // Some code
    }

    // Ball hit enemy or enemy hit ball
    if (firstBody.categoryBitMask == PhysicsCategory.ball) && (secondBody.categoryBitMask == PhysicsCategory.enemy) {

          // Some code
    }
}

另外,不要忘记在场景的didMoveToView中设置委托,以便工作。

physicsWorld.contactDelegate = self

希望这有帮助