当前位置: 首页 > 面试题库 >

如何在Swift,Sprite套件中检测碰撞

寇升
2023-03-14
问题内容

我在Swift中编写了这个简单的太空游戏,直到遇到碰撞检测问题为止。在浏览论坛,教程等之后,我尝试通过声明位掩码来实现冲突,如下所示:

对象1

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

对象2

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

我也将打印声明放在

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

这是我配置精灵的方法

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

创造敌人(被召唤进入查看功能)

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

和另一个精灵

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

这个是用计时器创建的

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

不幸的是,当我看到两个对象接触后,它无法在控制台中打印任何内容。


问题答案:
  1. 定义唯一的类别,确保您的班级是a SKPhysicsContactDelegate,并使自己成为物理联系人的代表:

//Physics categories

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

class GameScene: SKScene, SKPhysicsContactDelegate {
   physicsWorld.contactDelegate = self
  1. 分配类别(通常在didMove(to view:)

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

(确保已为每个节点创建了物理实体)

  1. 设置碰撞:

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

甚至:

for node in [enemy, bullet] {
   node.physicsBody?.collisionBitMask = 0 //  collides with nothing
   }
  1. 建立联络人

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

确保每个潜在接触中涉及的至少一个对象isDynamic的物理实体上的属性设置为true,否则将不会生成任何接触。两个对象都不必是动态的。

didBegin当子弹和敌人接触时,您现在应该被呼叫。您可以这样编写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")
     }

}



 类似资料:
  • 问题内容: 我想要一个精灵在触摸另一个精灵时将自身删除。现在,当他们触摸时,他们只是互相推动。 我有这个: 我使精灵充满活力,不受重力影响 和 我无法迅速找到对我有意义的任何东西,但我认为问题出在这里 问题答案: 首先,您应该将firstBody和secondBody设置为它们的crashBitMask的顺序: 这样可以防止您的精灵与任何物体(包括彼此)碰撞。在设置其他BitMask属性的位置进行

  • 我正在使用Sprite Kit中的碰撞检测。它在起作用,防止我的精灵穿越路径。然而,我在didBeginContact中没有收到通知:而且我似乎无法控制物理引擎在发生碰撞时的响应。 我让各种汽车(SKSpriteNodes)使用SKAction followPath沿着以下路径行驶:as offset:oriento path:duration: 以前,如果两辆车相交,它们都会像往常一样继续行驶,

  • 问题内容: 你好。 我有多个碰撞问题。有一颗子弹击中了敌人(红色矩形)。然后,它+分数。有一个螺旋线(红色圆圈) 被推测为当敌人(红色矩形)触摸场景时触发场景结束。 在这种情况下,当敌人击中螺旋桨时,螺旋桨将起作用,场景结束,然后我们进入菜单屏幕。但是,当子弹击中敌人时,同样的事情也会发生,我也不知道为什么。 现在,这是我的代码: 现在,我知道那是一团糟,但是有人可以帮助我吗?我认为问题与body

  • 我是IOS开发的新手,目前在didBeginContact方法中遇到一些sprite工具包冲突问题。 如果一个碰撞的物理物体被移走了,我如何摆脱或者停止didBeginContact的运行?例:一颗子弹与两个重叠的敌人相撞。因为子弹击中第一个敌人并被摧毁,所以在第二个敌人上运行的碰撞检查抛出异常,因为子弹不再存在。 我试过检查nil和NSNULL值,但运气不好。我收到的错误代码是“线程1:EXC_

  • 我需要在iPad精灵游戏中生成8个随机精灵对象。这些对象相当大,并且大小不同。它们不应该叠加。如果场景中生成的对象叠加,它将被删除(可选地,它会删除底层对象)。我一直在为Sprite Kit寻找一个像素完美的冲突检测框架或帮助类。到目前为止,我还没有找到教程或类似的东西。大多数人使用普通的冲突检测,这没有任何帮助,因为我的对象很大。我测试了标准方法,但它创建了矩形,使我的情况下的精灵区域更大。这是

  • 问题内容: 您好,我已经仔细阅读了文档,无法弄清楚如何在场景工具包中设置碰撞检测。可以请一个例子。请帮我,我非常渴望解决这个问题。谢谢! 编辑:您好,非常感谢,对不起,我忘了提及我的项目进展迅速。没什么大不了的,我大部分时间都可以自我翻译。 当对象碰撞并相互反弹时,我使BitMasks正常工作。但是我似乎无法使该功能正常工作 查看文档,看来我需要以某种方式将场景物理世界委托分配给该方法。我不确定该