ios - Erkennen von Kollisionen im Swift, Sprite-Kit



skphysicsbody (1)

  1. Definieren Sie eindeutige Kategorien, stellen Sie sicher, dass Ihre Klasse ein SKPhysicsContactDelegate und machen Sie sich selbst zum Ansprechpartner für Physik:

//Physics categories

let enemyCategory:    UInt32 = 1 << 1
let bulletCategory:   UInt32 = 1 << 2

class GameScene: SKScene, SKPhysicsContactDelegate {
   physicsWorld.contactDelegate = self
  1. Ordnen Sie die Kategorien zu (normalerweise in didMove(to view:) :

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

(Stellen Sie sicher, dass Sie Physikkörper für jeden Knoten erstellt haben.)

  1. Kollisionen einrichten:

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

oder auch:

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

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

isDynamic Sie sicher, dass für mindestens eines der Objekte, die an jedem potenziellen Kontakt beteiligt sind, die Eigenschaft isDynamic für den physischen Körper auf true festgelegt ist. isDynamic kein Kontakt generiert. Es ist nicht erforderlich, dass beide Objekte dynamisch sind.

Sie sollten jetzt didBegin , wenn die Kugel und der Feind Kontakt aufnehmen. Sie könnten didBegin wie didBegin :

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

}

Ich programmierte dieses einfache Weltraumspiel in Swift, bis ich auf das Problem stieß, Kollisionen zu erkennen. Nachdem ich mich in Foren, Tutorials usw. umgesehen hatte, versuchte ich, Kollisionen zu implementieren, indem ich Bitmasken wie folgt deklarierte:

Objekt 1

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

Objekt 2

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

Ich habe auch eine Druckerklärung in das

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

So konfiguriere ich meine 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!)
}

Feind erstellen (Called in hat sich bewegt, um die Funktion anzuzeigen)

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

und das andere 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!)
}

Dieser wird mit einem Timer erstellt

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

Leider wird in der Konsole nichts gedruckt, nachdem sich die beiden Objekte berührt haben.





skphysicsbody