ios swift sprite-kit skphysicsbody

ios - Cómo detectar colisiones en Swift, Sprite kit



sprite-kit skphysicsbody (1)

Estaba programando este sencillo juego espacial en Swift hasta que encontré el problema de detectar colisiones. Después de buscar en foros, tutoriales, etc., intenté implementar colisiones declarando las máscaras de bits así:

objeto 1

enemy?.physicsBody = SKPhysicsBody(circleOfRadius: ((enemy?.size.width)!/2)) enemy?.physicsBody?.categoryBitMask = enemyBitMask enemy?.physicsBody?.contactTestBitMask = bulletBitMask enemy?.physicsBody?.collisionBitMask = 0

objeto 2

bullet?.physicsBody? = SKPhysicsBody(rectangleOf: (bullet?.size)!) bullet?.physicsBody?.categoryBitMask = bulletBitMask bullet?.physicsBody?.contactTestBitMask = enemyBitMask bullet?.physicsBody?.collisionBitMask = 0 bullet?.physicsBody?.usesPreciseCollisionDetection = true

También puse una declaración impresa en el

func didBegin(_ contact: SKPhysicsContact) { print("Hello") }

Así es como configuro mis sprites:

func CreateNewEnemy() { var enemy : SKSpriteNode? let moveEnemyDown = SKAction.repeatForever(SKAction.moveBy(x: 0, y: -1, duration: 0.01)) let rotateEnemy = SKAction.repeatForever(SKAction.rotate(byAngle: 25, duration: 5)) let enemyXpos = randomNum(high: self.frame.size.width/2, low: -1 * self.frame.size.width/2) let enemyYpos = randomNum(high: 2.5*self.frame.size.height, low: self.frame.size.height/2) let enemyOrigin : CGPoint = CGPoint(x: enemyXpos, y: enemyYpos) enemy = SKSpriteNode(imageNamed: possibleEnemyImage[Int(arc4random_uniform(4))]) print(enemy?.size.height) enemy?.scale(to: CGSize(width: player.size.height, height: player.size.height)) print(enemy?.size.height) enemy?.position = enemyOrigin enemy?.run(moveEnemyDown) enemy?.run(rotateEnemy) let enemyRadius : CGFloat = (enemy?.size.width)!/2 print(enemyRadius) enemy?.physicsBody? = SKPhysicsBody(circleOfRadius: enemyRadius) enemy?.physicsBody?.categoryBitMask = enemyCategory enemy?.physicsBody?.contactTestBitMask = bulletCategory enemy?.physicsBody?.collisionBitMask = 0 enemy?.zPosition = 1 enemiesArray.append(enemy!) self.addChild(enemy!) }

para crear enemigo (Llamado en mover para ver la función)

func CreateAllEnemies(amountOfEnemies : UInt8) { for _ in 0...amountOfEnemies { CreateNewEnemy() } }

y el otro sprite

func CreateNewBullet() { let bulletOrigin : CGPoint = CGPoint(x: player.position.x, y: player.position.y+player.size.height/2) let moveBulletUp = SKAction.repeatForever(SKAction.moveBy(x: 0, y: 3, duration: 0.01)) var bullet : SKSpriteNode? bullet = SKSpriteNode(imageNamed: "bulletImage") bullet?.position = bulletOrigin bullet?.run(moveBulletUp) bullet?.physicsBody? = SKPhysicsBody(rectangleOf: (bullet?.size)!) bullet?.physicsBody?.categoryBitMask = bulletCategory bullet?.physicsBody?.contactTestBitMask = enemyCategory bullet?.physicsBody?.collisionBitMask = 0 bullet?.physicsBody?.isDynamic = true bullet?.physicsBody?.usesPreciseCollisionDetection = true bullet?.zPosition = 1 bulletsArray.append(bullet!) self.addChild(bullet!) }

este se crea con un temporizador

bulletTimer = Timer.scheduledTimer(timeInterval: 0.25, target: self, selector: #selector(CreateNewBullet) , userInfo: nil, repeats: true)

Desafortunadamente, no imprime nada en la consola después de ver los dos objetos en contacto.


  1. Defina categorías únicas, asegúrese de que su clase sea un SKPhysicsContactDelegate y SKPhysicsContactDelegate el delegado de contacto de física:

//Physics categories

let enemyCategory: UInt32 = 1 << 1 let bulletCategory: UInt32 = 1 << 2 class GameScene: SKScene, SKPhysicsContactDelegate { physicsWorld.contactDelegate = self

  1. Asigna las categorías (generalmente en didMove(to view:) :

    enemy.physicsBody.catgeoryBitMask = enemyCategory bullet.physicsBody.catgeoryBitMask = bulletCategory

(Asegúrate de haber creado cuerpos físicos para cada nodo)

  1. Configurar colisiones:

enemy.physicsBody?.collisionBitMask = 0 // enemy collides with nothing bullet.physicsBody?.collisionBitMask = 0 // bullet collides with nothing

o incluso:

for node in [enemy, bullet] { node.physicsBody?.collisionBitMask = 0 // collides with nothing }

  1. Configurar contactos

    bullet.physicsBody?.collisionBitMask = enemyCategory // bullet contacts enemy

Asegúrese de que al menos uno de los objetos involucrados en cada contacto potencial tenga la propiedad isDynamic en su cuerpo de física establecido en true , o no se generará ningún contacto. No es necesario que ambos objetos sean dinámicos.

Ahora deberías hacer que te didBegin llamar cuando la bala y el enemigo entren en contacto. Podrías codificar didBegin esta manera:

func didBegin(_ contact: SKPhysicsContact) { print("didBeginContact entered for /(String(describing: contact.bodyA.node!.name)) and /(String(describing: contact.bodyB.node!.name))") let contactMask = contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask switch contactMask { case bulletCategory | enemyCategory: print("bullet and enemy have contacted.") let bulletNode = contact.bodyA.categoryBitMask == bulletCategory ? contact.bodyA.node : contact.bodyB.node enemyHealth -= 10 bulletNode.removeFromParent default: print("Some other contact occurred") }

}