2016-12-22 2 views
1

У меня есть массив объектов Bullets and Enemies. Я хочу, чтобы игра проверяла каждый элемент в массивах, чтобы увидеть, произошло ли столкновение между ними или нет. Если было какое-либо столкновение, то повредите этого врага и удалите пулю. Прямо сейчас, каждый раз, когда пуля попадает в противника, она уменьшает здоровье ВСЕХ врагов в массиве, тем самым убивая их всех сразу. Как я могу сделать это так, чтобы он только уменьшал здоровье врага, на который я стреляю?Как обнаружить столкновение между двумя объектами в массиве (комплект Sprite)

//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 и нанести урон конкретному противнику.

Кроме того, я подозреваю, что вам не хватает некоторых контактов, потому что для контактных тестов, вы не проверять, если bodyA и bodyB физические тела перепутаны т.е.

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

bodyA может быть player и bodyB может быть 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 categoryBitMaskbulletCategory Если это так, то установите bullet, равный nodeA, в противном случае установить bullet в nodeB.

Обратите внимание, что если ваши категории являются более сложными (т.е. объекты могут принадлежать к нескольким категориям), это не будет работать, как простой и тесты (enemyCategory| bulletCategory) не будет соответствовать.

+0

Вы также можете спросить себя, почему вы держите массивы пуль и врагов. У вас может быть очень реальная причина, но есть и другие способы доступа к этим узлам - свойство children [] для SKScene и функции enumerateChildNodesWithName(), которые можно назвать, но 2. –

+0

Эй, спасибо за ваш ответ! Я очень ценю это! Теперь я знаю, почему мои столкновения происходили только в половине случаев! Тем не менее, я до сих пор не понимаю эту часть: «Все, что вам нужно сделать, это извлечь конкретного противника из объекта SKPhysicsContact и нанести урон этому конкретному противнику». Как мне это сделать без итерации, хотя мой массив? В вашем примере у вас есть «enemy.setHitPoints» (setPoints: enemy.getHitPoints() - pistol.getDamage()) ». Итак, как мне сказать, что такое «враг» или что я говорю? –

+0

@SamTrent Контакт SKOhysics имеет 2 свойства - bodyA и bodyB. Эти устройства SKOhysicsBodies и каждый из них имеют свойство «node», которое является узлом, связанным с этим физическим телом. Таким образом, строка fo code 'let враг = contact.bodyA.categoryBitMask == enemyCategory? contact.bodyA .... 'создает временный SKNode, равный фактическому врагу, участвующему в столкновении. –

Смежные вопросы