SpriteKit Swift:当bodyA同时与多个bodyB碰撞时,如何防止崩溃?

时间:2016-05-26 07:41:21

标签: ios swift sprite-kit collision-detection collision

SITUTATION:

已经广泛搜索过,没有找到解决方案。

例如,这没有帮助:Swift/SpriteKit Multiple Collision Detection?

问题:

我的代码工作正常,除非玩家同时击中两个不同的PhysicsCategory对象(例如,同时击落并击中地面和墙壁)。这使我的应用程序崩溃。

CODE:

struct PhysicsCategory {
    static let player: UInt32 = 0x1 << 1
    static let ground: UInt32 = 0x1 << 2
    static let wall: UInt32 = 0x1 << 3
    static let scoreWall: UInt32 = 0x1 << 4
}

func didBeginContact(contact: SKPhysicsContact) {
    let firstBody = contact.bodyA
    let secondBody = contact.bodyB

    if firstBody.categoryBitMask == PhysicsCategory.scoreWall && secondBody.categoryBitMask == PhysicsCategory.player || firstBody.categoryBitMask == PhysicsCategory.player && secondBody.categoryBitMask == PhysicsCategory.scoreWall {

        score += 1
        scoreLabel.text = "\(score)"

        updatePlayerColor()

    }

    else if firstBody.categoryBitMask == PhysicsCategory.wall && secondBody.categoryBitMask == PhysicsCategory.player || firstBody.categoryBitMask == PhysicsCategory.player && secondBody.categoryBitMask == PhysicsCategory.wall {

        lost = true

        self.scene?.speed = 0

        gameVC?.dismissViewControllerAnimated(false, completion: nil)

        //playDeathAnimation with completion block self.dismiss(VC)
    }

    else if firstBody.categoryBitMask == PhysicsCategory.ground && secondBody.categoryBitMask == PhysicsCategory.player || firstBody.categoryBitMask == PhysicsCategory.player && secondBody.categoryBitMask == PhysicsCategory.ground {

        lost = true

        self.scene?.speed = 0

        gameVC?.dismissViewControllerAnimated(false, completion: nil)

        //playDeathAnimation with completion block self.dismiss(VC)
    }
}

调试程序错误:

致命错误:索引超出范围。

我在寻找什么:

我只是想知道我的代码中是否已经考虑了双重碰撞。调试器错误是指我的代码中受冲突影响的其他部分。但这里添加的代码太多了。所以请回答以下问题:如何在ScoreWall和Wall之间的SpriteKit游戏中解决双重冲突?

3 个答案:

答案 0 :(得分:1)

尝试这样的事情?它应该删除你的代码重复,并防止你的游戏超过逻辑发生两次。

func didBeginContact(contact: SKPhysicsContact) {
    if (lost) {
        return
    }
    var a = contact.bodyA.categoryBitMask
    var b = contact.bodyB.categoryBitMask
    if a > b {
        swap(&a, &b)
    }

    if a == PhysicsCategory.player && b == PhysicsCategory.scoreWall {

        score += 1
        scoreLabel.text = "\(score)"

        updatePlayerColor()

    } else if a == PhysicsCategory.player && (b == PhysicsCategory.ground || b == PhysicsCategory.wall) {

        lost = true

        self.scene?.speed = 0

        gameVC?.dismissViewControllerAnimated(false, completion: nil)

        //playDeathAnimation with completion block self.dismiss(VC)
    }
}

答案 1 :(得分:1)

你有什么样的错误?

无论如何,在删除重要部分之前,您可能必须等待物理模拟的结束(不知道应用程序的整个逻辑)。因此,在碰撞检测中设置lost布尔条件是好的,但剩下的可能必须在didSimulatePhysicsdidFinishUpdate中完成。

答案 2 :(得分:1)

你不会发生双重碰撞。您将有2次单次碰撞,即didBeginContact将被调用一次,用于玩家与地面之间的碰撞,再次用于玩家与墙壁之间的碰撞。 SKPhysicsContact只能有2个实体。您的崩溃是由其他原因造成的,可能是因为删除了游戏VC?

有关“清洁工”的例子。版本didBeginContact,试试这个:

 func didBeginContact(contact: SKPhysicsContact) {

        let contactMask = contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask

        switch contactMask {
        // If the player and the scoreWall have collided:
        case .player | .scoreWall :
           score += 1
           scoreLabel.text = "\(score)"
           updatePlayerColor()

        // If the player and the wall have collided:
        case .player | .wall :
           lost = true
           self.scene?.speed = 0
           gameVC?.dismissViewControllerAnimated(false, completion: nil)

        // If the player and the ground have collided:
        case .player | .ground :
           lost = true
           self.scene?.speed = 0
           gameVC?.dismissViewControllerAnimated(false, completion: nil)

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