简单的SpriteKit接触检测(太空射击游戏)没有正确地进行

时间:2016-04-15 20:36:50

标签: swift sprite-kit xcode6 collision-detection uint32

我试图制作一个简单的太空射击游戏。接触应该发生在鱼雷和外星人或航天飞机和外星人之间。问题在于,第二次接触(穿梭与外星人)只发生在第一种接触发生后(鱼雷对外星人),而且他们并不总是精确。这是在类

之外创建的结构
struct PhysicsCategory {
static let alien : UInt32 = 1
static let torpedo : UInt32 = 2
static let shuttle : UInt32 = 3 }

返:

shuttle.physicsBody = SKPhysicsBody(rectangleOfSize: shuttle.size)
shuttle.physicsBody?.categoryBitMask = PhysicsCategory.shuttle
shuttle.physicsBody?.contactTestBitMask = PhysicsCategory.alien 
shuttle.physicsBody?.dynamic = false 
shuttle.physicsBody?.affectedByGravity = false

鱼雷:

torpedo.physicsBody = SKPhysicsBody(rectangleOfSize: torpedo.size)
torpedo.physicsBody?.categoryBitMask = PhysicsCategory.torpedo
torpedo.physicsBody?.contactTestBitMask = PhysicsCategory.alien
torpedo.physicsBody?.affectedByGravity = false
torpedo.physicsBody?.dynamic = false

异己:

alien.physicsBody = SKPhysicsBody(rectangleOfSize: torpedo.size)
alien.physicsBody?.categoryBitMask = PhysicsCategory.alien
alien.physicsBody?.contactTestBitMask = PhysicsCategory.torpedo
alien.physicsBody?.affectedByGravity = false
alien.physicsBody?.dynamic = true

最后,这是我的联系人代码:

    func didBeginContact(contact: SKPhysicsContact) {
    var firstBody : SKPhysicsBody = contact.bodyA
    var secondBody : SKPhysicsBody = contact.bodyB

    if ((firstBody.categoryBitMask == PhysicsCategory.alien) && (secondBody.categoryBitMask == PhysicsCategory.torpedo)) ||
    ((firstBody.categoryBitMask == PhysicsCategory.torpedo) && (secondBody.categoryBitMask == PhysicsCategory.alien)) {
        self.contactWithTorpedo(firstBody.node as! SKSpriteNode, torpedo: secondBody.node as! SKSpriteNode)
    } else if ((firstBody.categoryBitMask == PhysicsCategory.shuttle) && (secondBody.categoryBitMask == PhysicsCategory.alien)) {
            self.contactWithShuttle(firstBody.node as! SKSpriteNode, shuttle: secondBody.node as! SKSpriteNode)
    }
}


func contactWithTorpedo (alien: SKSpriteNode, torpedo : SKSpriteNode) {
    alien.removeFromParent()
    torpedo.removeFromParent()
    score++
    scoreLabel.text = "score: " + "\(score)"
}

func contactWithShuttle (alien:SKSpriteNode, shuttle:SKSpriteNode) {
    alien.removeFromParent()
    shuttle.removeFromParent()

    self.view?.presentScene(EndScene())

}

我不确定问题出在哪里,而且我已经看过几个教程也会这样做。我不知道它是否与之相关,但这不是iOS游戏,而是OSX。提前谢谢!

3 个答案:

答案 0 :(得分:1)

您可能会发现重构didBeginContact的问题不那么令人困惑,因为这会避免firstBody / secondbody的内容和复杂的if...then条件,以便查看已联系的内容:

func didBeginContact(contact: SKPhysicsContact) {
    let contactMask = contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask

    switch contactMask {
    case PhysicsCategory.alien | PhysicsCategory.torpedo:
       // alien and torpedo have contacted
       contact.bodyA.removeFromParent()
       contact.bodyB.removeFromParent()
       score += 1
       scoreLabel.text = "score: " + "\(score)"

    case PhysicsCategory.alien | PhysicsCategory.shuttle:
       // alien and shuttle have contacted
       contact.bodyA.removeFromParent()
       contact.bodyB.removeFromParent()

       self.view?.presentScene(EndScene())

    default :
        //Some other contact has occurred
        print("Some other contact")
    }
}

您可以根据需要为游戏中的所有联系人添加尽可能多的PhysicsCategory.enemy | PhysicsCategory.player个案例。对每个潜在的联系人进行单独编码,如果......那么......你就不会自己松开。

如果你确实只需要引用一个联系人中涉及的一个节点,(例如在敌人击中后移除玩家),你可以这样做:

let playerNode = contact.bodyA.categoryBitMask == PhysicsCategory.player ? contact.bodyA.node! : contact.bodyB.node!
playernode.removefromParent

答案 1 :(得分:0)

我建议您阅读有关SKPhysicsBody的文档。

  

场景中的每个物理主体最多可以分配32个不同的类别,每个类别对应于位掩码中的一个位。您可以定义游戏中使用的蒙版值。结合collisionBitMask和contactTestBitMask属性,您可以定义哪些物理实体彼此交互以及何时向您的游戏通知这些交互

首先,我将PhysicsCategory更改为

struct PhysicsCategory {
static let alien : UInt32 = 0x1 << 1
static let torpedo : UInt32 = 0x1 << 2
static let shuttle : UInt32 = 0x1 << 3 
}

然后

alien.physicsBody?.contactTestBitMask = PhysicsCategory.torpedo | PhysicsCategory.shuttle

希望这有帮助。

答案 2 :(得分:0)

所以我昨天真的设法解决了我的问题。我发布了更新的代码,以防它可以帮助某人。 课外:

<option>

然后,在我之前写的每个sprite中应用phyics之后,在类中:

struct PhysicsCategory {
static let player : UInt32 = 0x1 << 0
static let bullet : UInt32 = 0x1 << 1
static let enemy : UInt32 = 0x1 << 2}