【问题标题】:How can I require two collisions on one of my nodes before removing it from screen?在从屏幕上删除它之前,我如何要求我的一个节点发生两次碰撞?
【发布时间】:2016-01-18 08:51:17
【问题描述】:

我有一个基于碰撞的游戏,里面有导弹和炸弹。现在一切正常,只有 1 次碰撞,它会从屏幕上删除节点。

虽然我希望能够让我的“炸弹”中的第一个炸弹更难摧毁,所以我想要求它被击中两次。我该怎么做?

这是炸弹

func enemies() {

    let bomb1 = SKSpriteNode(imageNamed: "Bomb1")
    let bomb2 = SKSpriteNode(imageNamed: "bomb2")
    let bomb3 = SKSpriteNode(imageNamed: "Bomb3")
    let enemy = [bomb1, bomb2, bomb3]

    // Enemy Physics
    for bomb in enemy {
        bomb1.size = CGSize(width: 55, height: 55)
        bomb2.size = CGSize(width: 55, height: 70)
        bomb3.size = CGSize(width: 30, height: 30)
        bomb.physicsBody = SKPhysicsBody(circleOfRadius: bomb.size.width / 4)
        bomb.physicsBody?.categoryBitMask = PhysicsCategory.enemy
        bomb.physicsBody?.collisionBitMask = PhysicsCategory.missile | PhysicsCategory.airDefense
        bomb.physicsBody?.contactTestBitMask = PhysicsCategory.missile | PhysicsCategory.airDefense
        bomb.physicsBody?.affectedByGravity = false 
        bomb.physicsBody?.dynamic = true
        bomb1.name = "enemy1"
        bomb2.name = "enemy2"
        bomb3.name = "enemy3"

    }

这是炸弹击中导弹时调用的函数。

 func collisionWithMissile(enemy : SKSpriteNode, missile : SKSpriteNode) {
    enemy.physicsBody?.dynamic = true
    enemy.physicsBody?.affectedByGravity = true
    missile.physicsBody?.affectedByGravity = true

    enemy.physicsBody?.mass = 10.0
    missile.physicsBody?.mass = 5.0

    enemy.removeAllActions()
    missile.removeAllActions()

    enemy.removeFromParent()
    missile.removeFromParent()

    enemy.physicsBody?.contactTestBitMask = 0
    enemy.physicsBody?.collisionBitMask = 0
    enemy.name = nil

    score++
    scoreLbl.text = "\(score)"

}

这可能有助于解决我遇到的错误

func didBeginContact(contact: SKPhysicsContact) {
    if contact.bodyA.node != nil && contact.bodyB.node != nil {
        let firstBody = contact.bodyA.node as! Bomb
        let secondBody = contact.bodyB.node as! SKSpriteNode

        // Bomb1 **********
        if ((firstBody.name == "enemy1") && (secondBody.name == "missile")) {

            collisionWithMissile(firstBody, missile: secondBody)
            atomicExplosion(contact.bodyA.node!.position)
            missileExplosion(contact.bodyB.node!.position)

        }

【问题讨论】:

  • 您可以使用字符串插值来简化enemies 方法。例如,您可以使用 let bomb = SKSpriteNode(imageNamed:"Bomb\(i)") 在 for 循环中创建每个炸弹,并使用 bomb.name = "enemy\(i)" 指定名称,其中 i(从 1...3)是循环控制变量。

标签: swift sprite-kit collision-detection skphysicsbody sknode


【解决方案1】:

您可以为您的炸弹子类化 SKSpriteNode,并为此类添加一个碰撞计数器。在您的 collisionWithMissile 函数中,您检查此计数器的值并在达到给定值时移除炸弹,否则您增加计数器。

您的子类可能如下所示

class Bomb: SKSpriteNode {
  var hitCount: Int

  init(imageNamed: String, hitCount: Int) {
    self.hitCount = hitCount
    let texture = SKTexture(imageNamed: imageNamed)
    super.init(texture: texture, color: UIColor.clearColor(), size: texture.size())
  }

  required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
  }
}

init 方法以 hitCount 作为参数,因此您可以轻松创建不同强度的炸弹。您的 collisionWithMissile 方法可能是这样的。只需用您需要的代码填充 if-else 部分。

func collisionWithMissile(enemy : Bomb, missile : SKSpriteNode) {
  if enemy.hitCount <= 0 {
      enemy.removeFromParent()
  } else {
      enemy.hitCount -= 1
  }
}

【讨论】:

  • 如果你不想子类化,并且想要一个看起来损坏的效果,你可以使用 alpha 作为“生命计数器”,然后随着更多的损坏发生,它变得越透明
  • @Pierre 你能给我举个例子吗?
  • @TimmySorensen 看看我编辑的答案。我不知道你的项目是什么样子的,也许对 Bomb 类使用另一个 init 方法会更容易,它只接受 hitCount 作为参数。
  • @Pierre 所以我会使用子类 Bomb 而不是我在顶部的 func 敌人?每个炸弹都有一个子类吗?我没有要设置的颜色,所以我试着把它拿出来,但出错了,所以不知道该怎么办。抱歉这是我第一次使用子类,感谢您的帮助!
  • @TimmySorensen 我更改了 init 方法,使其与您使用的方法相似。对你的问题:你的炸弹只有这个子类。在你的敌人()函数中,你只需将第一行从let bomb1 = SKSpriteNode(imageNamed: "Bomb1")更改为let bomb1 = Bomb(imageNamed: "Bomb1", hitCount: theHitCountYouWant)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多