【问题标题】:How to detect a collision between two objects in an Array (Sprite Kit)如何检测数组中两个对象之间的碰撞(Sprite Kit)
【发布时间】:2016-12-22 00:58:47
【问题描述】:

我有一系列 Bullets 和 Enemies 对象。我希望游戏检查数组中的每个元素,看看两者之间是否存在冲突。如果发生任何碰撞,则伤害该敌人并删除子弹。现在,每次子弹击中敌人时,都会降低阵列中所有敌人的生命值,从而一次性杀死他们。我怎样才能让它只降低我正在射击的敌人的生命值?

 //This function handles our collision detection
    func didBegin(_ contact: SKPhysicsContact) {
        //print("COLLISIONS!")
        // If contact is with another object
        if contact.bodyA.categoryBitMask == pickupCategory && contact.bodyB.categoryBitMask == playerCategory
        {
            displayText(text: "Picked up Pistol")
            player.setHasPistol(gotPistol: true)
            pistol.removeFromParent()
        }

        //Bullet hits an object
        if contact.bodyA.categoryBitMask == objectCategory && contact.bodyB.categoryBitMask == bulletCategory
        {
            bulletCleanup(killNow: true)
            //print("BULLET HAS HIT THE PIPE!")
        }

        //Do collisions between bullets and enemies...
        for bullet in bulletList
        {
            for enemy in enemyList
            {
                //if the enemy was hit have them take damage.
                if contact.bodyA.categoryBitMask == enemyCategory && contact.bodyB.categoryBitMask == bulletCategory
                {
                    //deletes the bullet after hitting an object
                    bulletCleanup(killNow: true)

                    //apply damage
                    enemy.setHitPoints(setPoints: enemy.getHitPoints() - pistol.getDamage())

                    // print("BULLET HAS HIT THE enemy!!!!")
                }
            }
        }
    }

【问题讨论】:

    标签: arrays collections sprite-kit


    【解决方案1】:

    didBegin(contact:) 被调用用于一个特定对象和另一个特定对象之间的单个碰撞。 (实际上是物理体之间……)

    您的问题正在发生,因为您正在迭代 每个 子弹和 每个 敌人进行一次碰撞,并且在每次迭代中,您都在测试碰撞是否发生在子弹和一个敌人,它是,所以你正在对每个敌人施加伤害。

    您需要做的就是从SKPhysicsContact 对象中提取特定敌人并对特定敌人施加伤害。

    另外,我怀疑您缺少一些联系人,因为对于您的联系人测试,您没有检查 bodyAbodyB 物理体是否颠倒,即

    if contact.bodyA.categoryBitMask == pickupCategory && contact.bodyB.categoryBitMask == playerCategory
    

    bodyA 可能是 playerbodyB 可能是 pickup,因此您还需要对此进行测试。

    这里有一个替代的 didBegincontact() 你可能会觉得有帮助(它是 Swift2,但这应该不是什么大问题):

    func didBeginContact(contact: SKPhysicsContact) {
        let contactMask = contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask
    
    switch contactMask {
    
       case pickupCategory  | playerCategory
            displayText(text: "Picked up Pistol")
            player.setHasPistol(gotPistol: true)
    
           let pistol = (contact.bodyA.categoryBitMask == pickupCategory) ? contact.bodyA.node! : contact.bodyB.node!
    
            pistol.removeFromParent()
    
       case objectCategory | bulletCategory
            bulletCleanup(killNow: true)
            //print("BULLET HAS HIT THE PIPE!")
    
       case enemyCategory| bulletCategory
    
            //deletes the bullet after hitting an object
            bulletCleanup(killNow: true)
    
            //apply damage
           let enemy = (contact.bodyA.categoryBitMask == enemyCategory) ? contact.bodyA.node! : contact.bodyB.node!
            enemy.setHitPoints(setPoints: enemy.getHitPoints() - pistol.getDamage())
    
       default :
           //Some other contact has occurred
           print("Some other contact")
       }
    }
    

    我不确定您的 bulletCleanup() 函数是如何工作的 - 您似乎没有向它发送特定的项目符号对象,所以我不知道它如何知道要处理哪个项目符号。联系人中涉及的具体项目符号可以在didBegincContact:获取,如下:

           let bullet = (contact.bodyA.categoryBitMask == bulletCategory) ? contact.bodyA.node! : contact.bodyB.node!
    

    这是“nodeA's categoryBitMask a bulletCategory? 的简写形式?如果是,则将bullet 设置为等于nodeA,否则将bullet 设置为nodeB

    请注意,如果您的类别更复杂(即对象可以属于多个类别),这将不起作用,因为简单的 AND 测试 (enemyCategory| bulletCategory) 将不匹配。

    【讨论】:

    • 您可能还想问自己为什么要保留一系列子弹和敌人。您可能有一个非常真实的原因,但还有其他方法可以访问这些节点 - SKScene 的 children[] 属性和 enumerateChildNodesWithName() 函数命名为 2。
    • 嗨,谢谢您的回复!对此,我真的非常感激!现在我知道为什么我的碰撞只发生了一半!但是,我仍然不明白这部分,“你需要做的就是从 SKPhysicsContact 对象中提取特定的敌人并对那个特定的敌人施加伤害。”如何在不迭代数组的情况下做到这一点?在您的示例中,您有“enemy.setHitPoints(setPoints:enemy.getHitPoints() - pistol.getDamage())”。那么我如何告诉函数什么是“敌人”或者我在说哪一个。
    • @SamTrent SKOhysics 联系人有 2 个属性 - bodyA 和 bodyB。这些 ar SKOhysicsBodies 中的每一个都有一个属性“节点”,它是与该物理体相关联的节点。所以代码行'让敌人=contact.bodyA.categoryBitMask ==enemyCategory? contact.bodyA....' 创建一个临时的 SKNode 等于碰撞中涉及的实际敌人。
    • 嘿,我明白了!这就是我所做的,'让敌人:敌人=(contact.bodyA.categoryBitMask ==enemyCategory?contact.bodyA.node!as!敌人:contact.bodyB.node!as!SKSpriteNode as!敌人)敌人.setHitPoints(setPoints :enemy.getHitPoints() - pistol.getDamage())" 我刚刚把所有东西都交给了 Enemy。不确定这是否是最好的做法,但它确实有效!再次感谢您的帮助!
    • @SamTrent - 你明白了。很多(全部?)Sprite-kit 向您的代码返回节点的函数,它将作为 SKNode 返回,因此您必须将其转换为您期望的或测试它,例如使用 enumerateChildNodesWithName 时,通常会执行 'if let myNode = returnedNode as! xxxx等
    猜你喜欢
    • 2014-01-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-19
    • 2015-02-18
    相关资源
    最近更新 更多