0

Итак, у меня есть два объекта, которые должны потерять точки здоровья при столкновении.Обнаружение столкновения Swift/SpriteKit между многими объектами

func addPlayer(xPos: CGFloat, yPos: CGFloat){ 
    playerNode = SKSpriteNode(imageNamed: "player") 

    playerNode.physicsBody = SKPhysicsBody(circleOfRadius: width/2) 
    playerNode.physicsBody!.affectedByGravity = false 
    playerNode.physicsBody!.categoryBitMask = PhysicsCategory.Player 
    playerNode.physicsBody!.contactTestBitMask = PhysicsCategory.Wall | PhysicsCategory.Zombie 
    playerNode.physicsBody!.collisionBitMask = PhysicsCategory.Wall | PhysicsCategory.Zombie 
    playerNode.name = "Player" 

    player = Player(node: playerNode, healthPoints: 100, attack: 10) 
    playerNode.position.x = xPos 
    playerNode.position.y = yPos 
    playerNode.size = CGSize(width: width, height: width) 
    addChild(playerNode) 
} 

func addZombie(xPos: CGFloat, yPos: CGFloat){ 

    zombieNode = SKSpriteNode(imageNamed: "zombie") 

    zombieNode.physicsBody = SKPhysicsBody(circleOfRadius: width/2) 
    zombieNode.physicsBody!.affectedByGravity = false 
    zombieNode.physicsBody!.categoryBitMask = PhysicsCategory.Zombie 
    zombieNode.physicsBody!.contactTestBitMask = PhysicsCategory.Zombie | PhysicsCategory.Player | PhysicsCategory.Wall 
    zombieNode.physicsBody!.collisionBitMask = PhysicsCategory.Zombie | PhysicsCategory.Player | PhysicsCategory.Wall 
    zombieNode.name = "Zombie" 

    zombie = Zombie(node: zombieNode, healthPoints: 50, attack: 5) 
    Zombies.append(zombie!) 
    zombieNode.position.x = xPos 
    zombieNode.position.y = yPos 
    zombieNode.size = CGSize(width: width, height: width) 
    addChild(zombieNode) 
} 

При столкновении появляется эта функция будет активизироваться:

func didBeginContact(contact: SKPhysicsContact) { 
    let firstBody = contact.bodyA.node as! SKSpriteNode 
    let secondBody = contact.bodyB.node as! SKSpriteNode 
    if(firstBody.name == "Player" && secondBody.name == "Zombie"){ 
     changeHealthPointsForZombieWithNode(secondBody, points: player!.attack) 
    } else if(firstBody.name == "Zombie" && secondBody.name == "Player"){ 
     changeHealthPointsForPlayer(secondBody, points: zombie!.attack) 
     print(player!.healthPoints) 
    } 
} 

func changeHealthPointsForZombieWithNode(node: SKSpriteNode, points: Int) { 
    for zombie in Zombies { 
     if zombie.node == node { 
      zombie.healthPoints -= points 
      print(zombie.healthPoints) 
      if(zombie.healthPoints <= 0){ 
       zombieNode.removeFromParent() 
      } 
      return 
     } 
    } 
} 

func changeHealthPointsForPlayer(node: SKSpriteNode, points: Int) { 
    player!.healthPoints -= points 
    if(player!.healthPoints <= 0){ 
     playerNode.removeFromParent() 
     gameOver = true 
    } 
} 

Я хочу, чтобы вычесть очки здоровья зомби в зависимости от атаки игрока и наоборот. Когда игрок бьет зомби, зомби должен потерять очки жизни. Когда зомби попадает в игрока, игрок должен потерять очки жизни. Каждый игрок/зомби получил очки здоровья и значение атаки. Проблема в том, что некоторые зомби являются убиваемыми и теряют здоровье, а другие (обычно 1-3) не могут потерять здоровье. Эти зомби, которые не могут потерять здоровье, являются единственными, кто может убить игрока. Зомби, которые теряют здоровье, не могут нанести урон (почему?)? Таким образом, можно только сделать одно (атаковать или потерять здоровье), хотя они должны иметь возможность делать две вещи (атаковать и терять здоровье).

+0

im немного запутался, говорим ли мы, что если игрок попадает в зомби, зомби теряет жизнь, если зомби попадает в игрока, игрок теряет жизнь, но игрок и зомби одновременно могут столкнуться? – Knight0fDragon

+0

@ Knight0fDragon Почему они должны сталкиваться одновременно? С кем-то кто-то сталкивается. Если игрок - тот, кто работает в зомби, зомби должен потерять жизнь. Если зомби - тот, который работает в плеере, игрок должен потерять жизнь. –

+0

хорошо, вам нужно думать, как машина здесь, я не думаю, что набор спрайтов достаточно умен, чтобы определить, кто сталкивается с кем, просто они оба столкнулись, так что вы можете пропустить звонки, потому что вы видите его как игрока Zombie, но код видит, что Zombie ударил игрока при обработке – Knight0fDragon

ответ

0

Имейте в виду, что два физических тела, описанные в параметре контакта, не передаются в гарантированном порядке. Внутри функции delegate нет такой вещи, как «A - это столкновение с B, а не наоборот». Существует только «A и B сталкиваются». Тем не менее, у вас есть два варианта, по крайней мере, в зависимости от вашей игровой механики:

  • Сделать игроком и зомби наносить урон друг другу каждый раз, когда они сталкиваются.
  • Сделать для игрока и зомби подкласс SKSpriteNode с имуществом isAttacking, логическим для определения того, когда сущность должна нанести урон при обнаружении контакта с ним. Для игрока это логическое значение может быть активировано каждой кнопкой/нажатием кнопки. Для зомби время от времени, если достаточно близко к игроку.

Кроме того, способ, которым вы воспользовались, будет получать уведомления о двойном контакте. SpriteKit обнаружит, что игрок находится в контакте с зомби, маской контактной маски и маской категории зомби и что зомби находится в контакте с игроком, с помощью маски контакта с зомби и маски категории игрока. Обычно вы этого не хотите. Вы должны заставить только одного из них обнаружить его. Я бы предложил игрока. Таким образом, нет необходимости устанавливать контактную маску зомби. Пока вы устанавливаете зомби в контактную маску игрока и маску категории зомби, у вас уже будет обнаружение (и один раз).