当玩家节点与另一个节点发生碰撞时游戏结束,此时游戏应该仅在玩家与边界碰撞时结束

时间:2016-06-10 06:07:47

标签: swift sprite-kit collision-detection skspritenode skphysicsbody

问题:当玩家节点与硬币节点接触时,游戏结束时游戏应该只在玩家与边界碰撞时结束。

输出应该是什么:播放器应该能够与硬币节点接触并穿过它,向scoreLabel添加一个值。 目前的代码:

 struct ColliderType {

static let playerCategory: UInt32 = 0x1 << 0
static let boundary: UInt32 = 0x1 << 1
static let coinCategory: UInt32 = 0x1 << 2
static let firstBody: UInt32 = 0x1 << 3
static let secondBody: UInt32 = 0x1 << 4

}

   var gameOver = false
   var coinInt = 0

    coin.physicsBody?.categoryBitMask = ColliderType.coinCategory
    coin.physicsBody?.contactTestBitMask = ColliderType.playerCategory
    coin.physicsBody?.collisionBitMask = 0


    player.physicsBody?.categoryBitMask = ColliderType.playerCategory
    player.physicsBody?.contactTestBitMask = ColliderType.boundary | ColliderType.coinCategory
    player.physicsBody?.collisionBitMask = ColliderType.boundary

func didBeginContact(contact:SKPhysicsContact) {
    var firstBody: SKPhysicsBody
    var secondBody: SKPhysicsBody

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


    } else{

        firstBody = contact.bodyB
        secondBody = contact.bodyA

    }

    if firstBody.categoryBitMask == ColliderType.playerCategory && secondBody.categoryBitMask == ColliderType.coinCategory {
       self.coin.removeFromParent()
       coinInt += 1
       coinLabel.text = "\(coinInt)"
    }

    gameOver = true
    self.speed = 0
    timer.invalidate()

}

override func touchesBegan(touches: Set<UITouch> , withEvent event: UIEvent?) {
    if gameOver == false {

    self.player.physicsBody?.velocity = CGVectorMake(1, 3)
    self.player.physicsBody?.applyImpulse(CGVectorMake(0, 12))

    }

}

更新:

    boundary.contactTestBitMask = ColliderType.playerCategory
    boundary.categoryBitMask = ColliderType.boundary
    boundary.collisionBitMask = ColliderType.playerCategory

   coin.physicsBody?.categoryBitMask = ColliderType.coinCategory
   coin.physicsBody?.contactTestBitMask = ColliderType.playerCategory
   coin.physicsBody?.collisionBitMask = 0


    player.physicsBody?.categoryBitMask = ColliderType.playerCategory
    player.physicsBody?.contactTestBitMask = ColliderType.coinCategory
    player.physicsBody?.collisionBitMask = ColliderType.boundary




func didBeginContact(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

    }


    if firstBody.categoryBitMask == ColliderType.coinCategory || secondBody.categoryBitMask == ColliderType.coinCategory {

    self.coin.removeFromParent()
    self.coinInt += 1
    self.coinLabel.text = "\(self.coinInt)"

    }else if firstBody.categoryBitMask == ColliderType.boundary || secondBody.categoryBitMask == ColliderType.boundary {

    gameOver = true
    self.speed = 0
    timer.invalidate()

}
}

3 个答案:

答案 0 :(得分:2)

您的gameOver = true语句超出了didBeginContact中的所有if。换句话说:发生联系的那一刻你设置gameOver = true。

if firstBody.categoryBitMask == ColliderType.coinCategory || secondBody.categoryBitMask == ColliderType.coinCategory {
   self.coin.removeFromParent()
   coinInt += 1
   coinLabel.text = "\(coinInt)"
} else if firstBody.categoryBitMask == ColiderType.boundary || secondBody.categoryBitMask == ColiderType.boundary {
    gameOver = true
    self.speed = 0
    timer.invalidate()
}

可能更接近你想要的东西。

答案 1 :(得分:1)

使用firstBody / secondbody编写代码didBeginContact的更简洁的方法是:

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

        switch contactMask {

        case ColliderType.playerCategory | ColliderType.coinCategory:
            // player and coin have contacted. We need to get the coin, which is either firstBody or secondBody,  to remove it, so assign the corect one to coinNode
            let coinNode = contact.bodyA.categoryBitMask == ColliderType.coinCategory ? contact.bodyA.node! : contact.bodyB.node!
             coinNode.removefromParent
             coinInt += 1
             coinLabel.text = "\(coinInt)"

        case ColliderType.playerCategory | ColliderType.boundaryCategory:
            // player and boundary have contacted
                gameOver = true
            self.speed = 0
            timer.invalidate()

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

您可以根据需要添加任意数量的case ColliderType.object1 | ColliderType.object2:

答案 2 :(得分:1)

(添加新答案,因为它基于新代码和O.P.问题中的讨论/更改会使逻辑流程难以理解)

首先,我会对physicBodies进行以下更改:

player.physicsBody?.contactTestBitMask = 0 // or ColliderType.None which would be my stylistic choice

然后其他人会读到这样的东西。

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

    if firstBody.categoryBitMask == ColliderType.coinCategory || secondBody.categoryBitMask == ColliderType.coinCategory {
        self.coin.removeFromParent()
        self.coinInt += 1
        self.coinLabel.text = "\(self.coinInt)"
    } else if firstBody.categoryBitMask == ColliderType.boundary || secondBody.categoryBitMask == ColliderType.boundary {
        gameOver = true
        self.speed = 0
        timer.invalidate()
    }
}

备注: 从提供的代码中不清楚self.coin是如何被引用的。我猜测 self.coin.removeFromParent()可能没有多大意义,因为您在初始帖子中写了几个硬币。它可能应该是这样的:

if contact.bodyA.categoryBitMask == ColliderType.coinCategory {
    contact.bodyA.node!.removeFromParent()
} else if contact.bodyB.categoryBitMask == ColliderType.coinCategory {
    contact.bodyB.node!.removeFromParent()
}

但我真的认为将整个联系处理完全重新组合成一个不同的野兽如果你打算在这个方面进行扩展。