2016-12-22 43 views
1

我有一个Bullets和Enemies对象的数组。我希望游戏检查数组中的每个元素,看看两者之间是否有碰撞。如果发生任何碰撞,则伤害敌人并删除子弹。现在每次子弹击中敌人时,它都会降低阵列中所有敌人的健康,从而一次杀死所有敌人。我怎么能这样做,它只会减少我射击的敌人的健康状况?如何检测阵列中两个对象之间的碰撞(Sprite Kit)

//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!!!!") 
       } 
      } 
     } 
    } 

回答

2

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! 

这是说短形式“是nodeAcategoryBitMask一个bulletCategory如果是,则设置bullet等于nodeA,否则设置bulletnodeB

请注意,如果您的类别比较复杂(即对象可以属于多个类别),这将不会是简单和试验(enemyCategory| bulletCategory)工作将不匹配。

+0

你可能也想问自己为什么你要保持子弹和敌人的阵列。您可能有一个非常真实的原因,但有其他方法来访问这些节点 - SKScene的children []属性和enumerateChildNodesWithName()函数来命名,但是2. –

+0

嘿,人感谢您的回应!对此,我真的非常感激!现在我知道为什么我的碰撞只发生在一半的时间!然而,我仍然不理解这个部分,“你只需要从SKPhysicsContact对象中提取特定的敌人并对该特定的敌人施加伤害。”我怎么做,而不是迭代通过我的数组?在你的例子中,你有“enemy.setHitPoints(setPoints:enemy.getHitPoints() - pistol.getDamage())”。那么,我如何告诉函数“敌人”是什么或者我正在谈论哪一个。 –

+0

@SamTrent SKOhysics联系人有2个属性 - bodyA和bodyB。这些是物理体,每一个都有一个属性“节点”,它是与该物理体相关的节点。因此,代码行'let enemy = contact.bodyA.categoryBitMask == enemyCategory? contact.bodyA ....'会创建一个与冲突中涉及的实际敌人相同的临时SKNode。 –