SpriteKit碰撞检测无法正常工作

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SpriteKit碰撞检测无法正常工作相关的知识,希望对你有一定的参考价值。

我的游戏中有三个节点 -

玩家;选手 -

这是一艘你用操纵杆拖动的船。

let collisionPlayer : UInt32 = 0x1 << 1

let apple = SKSpriteNode(texture: texture)
    apple.position = position
    apple.physicsBody = SKPhysicsBody(circleOfRadius: apple.size.width / 2.0)
    apple.physicsBody?.affectedByGravity = false
    apple.physicsBody?.isDynamic = true
    apple.setScale(0.1)
    addChild(apple)

(“苹果”是船)

敌人船 -

这是一个随机跟随玩家的CPU船。

 let collisionNPC : UInt32 = 0x1 << 0


 appleNPC.position = position
    appleNPC.physicsBody = SKPhysicsBody(circleOfRadius: appleNPC.size.width / 2.0)
    appleNPC.physicsBody?.isDynamic = true
    appleNPC.physicsBody?.affectedByGravity = false
    appleNPC.position = CGPoint(x: 600, y: 200)

    appleNPC.setScale(0.1)
    addChild(appleNPC)

子弹(不言自明)

let collisionBullet : UInt32 = 0x1 << 2

(以下代码在TouchesEnded中)

  bullet?.name = "Bullet"
    bullet?.position = (appleNode?.position)!
    bullet?.setScale(0.05)
    bullet?.zPosition = 1
    bullet?.physicsBody = SKPhysicsBody(circleOfRadius: (bullet?.size.width)!/2)
    bullet?.physicsBody?.isDynamic = true
    bullet?.physicsBody?.affectedByGravity = false
    bullet?.physicsBody?.usesPreciseCollisionDetection = true

要移动子弹我使用代码:

    // Your code with delay
    if bulletNumbers > 0 {
        let offset = CGPoint(x: touchLocation.x - (bullet?.position.x)! , y: touchLocation.y - (bullet?.position.y)!)

        //Stops Bullet from shooting backwards


        //Get the direction of where to shoot
        let direction = offset

        //Make it shoot far enough to be guaranteed off screen
        let shootAmount = CGPoint(x: direction.x * 10, y: direction.y * 10)

        //Add the shoot amount to the current position
        let realDest = CGPoint(x: shootAmount.x + (bullet?.position.x)!, y: shootAmount.y + (bullet?.position.y)!)

        //Create the actions
        addChild(bullet!)
        self.bulletNumbers -= 1

        let distance = sqrt(pow(realDest.x - (appleNode?.position.x)!, 2) +
            pow(realDest.y - (appleNode?.position.y)!, 2))

        // run the sequence of actions for the firing
        let duration = TimeInterval(distance / PlayerMissileSpeed)
        let missileMoveAction = SKAction.move(to: realDest, duration: duration)
        let when = DispatchTime.now() + 10 // change 2 to desired number of seconds
        DispatchQueue.main.asyncAfter(deadline: when) { self.bulletNumbers += 1
        }
        bullet?.run(missileMoveAction) {
        self.bullet?.isHidden = true
        self.bullet?.removeFromParent()
        print("(self.bulletNumbers)")
        }}
    else if bulletNumbers <= 0 {
      print("reload")

        let when = DispatchTime.now() + 2 // change 2 to desired number of seconds
        DispatchQueue.main.asyncAfter(deadline: when) {

        }

    }


}

func didBegin(_ contact: SKPhysicsContact) {
    print("test")


}

func setRandomStickColor() {
    let randomColor = UIColor.random()
    moveAnalogStick.stick.color = randomColor
}

func setRandomSubstrateColor() {
    let randomColor = UIColor.random()
    moveAnalogStick.substrate.color = randomColor
}

override func update(_ currentTime: TimeInterval) {
    /* Called before each frame is rendered */
    super.update(currentTime)
    let _:UInt32 = arc4random_uniform(1) //

    appleNodeCpuSpeed = CGFloat(1)


    var locationx : CGFloat
    var locationy: CGFloat

    locationx = (appleNode?.position.x)!
    locationy = (appleNode?.position.y)!
    let dx = locationx - (appleNodeNPC?.position.x)!
    let dy = locationy - (appleNodeNPC?.position.y)!
    let angle = atan2(dy, dx)
    let vx = cos(angle) * appleNodeCpuSpeed
    let vy = sin(angle) * appleNodeCpuSpeed


    self.appleNodeNPC?.position.x += vx
    self.appleNodeNPC?.position.y += vy

    let when = DispatchTime.now() + 0.25 // change 2 to desired number of seconds
    DispatchQueue.main.asyncAfter(deadline: when) {

          self.appleNodeNPC?.zRotation = angle + 90

    }
    //2

这很好用。子弹从船上发射到触摸位置,然而,当我试图引入碰撞时,事情开始出错。这是我的代码如下:

 appleNode?.physicsBody?.categoryBitMask = collisionPlayer
    appleNode?.physicsBody?.collisionBitMask = collisionNPC
    appleNode?.physicsBody?.contactTestBitMask = 0

    appleNodeNPC?.physicsBody?.categoryBitMask = collisionNPC
    appleNodeNPC?.physicsBody?.collisionBitMask = collisionPlayer
    appleNodeNPC?.physicsBody?.contactTestBitMask = collisionBullet

    bullet?.physicsBody?.categoryBitMask = collisionBullet
    bullet?.physicsBody?.collisionBitMask = 0
    bullet?.physicsBody?.contactTestBitMask = collisionNPC


    physicsWorld.contactDelegate = self
    view.showsPhysics = true

然后在我的didBegin函数中,我有:

func didBegin(_ contact: SKPhysicsContact) {
    print("test")


}

让我们从头开始。我点击屏幕,发射子弹。子弹不会与玩家碰撞,这是我最初想要的。然而,当子弹与敌舰接触时,它会发生碰撞。它环绕着船只并继续前往其原始目的地。我希望子弹与船只联系而不是其他任何东西 - 没有碰撞。我希望假设我的错误是因为我移动子弹的代码,但我不确定。任何帮助表示赞赏。

答案
  1. 定义独特的类别,确保您的课程是SKPhysicsContactDelegate并让自己成为物理联系代表:

//Physics categories

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

class GameScene: SKScene, SKPhysicsContactDelegate {
   physicsWorld.contactDelegate = self
  1. 分配类别(通常在didMove(to view:)中: apple.physicsBody.catgeoryBitMask = appleCategory enemy.physicsBody.catgeoryBitMask = enemyCategory bullet.physicsBody.catgeoryBitMask = bulletCategory

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

  1. 设置碰撞:

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

甚至:

for node in [apple, 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")
     }

}

以上是关于SpriteKit碰撞检测无法正常工作的主要内容,如果未能解决你的问题,请参考以下文章

未检测到 SpriteKit 碰撞

Monogame碰撞检测无法正常工作

未检测到 SpriteKit 碰撞

横向模式在 spritekit 游戏中无法正常工作

未检测到 spritekit 物理碰撞

iOS - bodyWithPolygonFromPath : Body 与路径相同,但碰撞无法正常工作