1

我正在尝试制作一个简单的太空射击游戏。接触应该发生在鱼雷和外星人之间,或者航天飞机和外星人之间。问题是第二次接触(航天飞机与外星人)仅在第一种接触发生后(鱼雷与外星人)发生,而且它们并不总是准确的。这是在类之外创建的结构

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。先感谢您!

4

3 回答 3

1

You might find it less confusing to restructure your didBeginContact as follows, as this avoids the firstBody/secondbody stuff and the complicated if...then conditions to see what has contacted what:

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

You can just add as many PhysicsCategory.enemy | PhysicsCategory.player cases as you need for all the contacts that you have to take action for in your game. Code each potential contact individually and you won't loose yourself in if...then...else.

if you do need to reference only one of the nodes involved in a contact, (e.g. to remove the player after an enemy hits it), you can do it like this:

let playerNode = contact.bodyA.categoryBitMask == PhysicsCategory.player ? contact.bodyA.node! : contact.bodyB.node!
playernode.removefromParent
于 2016-04-19T11:48:49.083 回答
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

希望这可以帮助。

于 2016-04-15T21:32:26.607 回答
0

所以我昨天实际上已经解决了我的问题。我发布更新的代码以防它可以帮助某人。课外:

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

然后,在将物理应用到我之前写的每个精灵之后,在课堂内:

    //Contact with bullet
func contactWithBullet(enemy : SKSpriteNode, bullet: SKSpriteNode) {
    enemy.removeFromParent()
    bullet.removeFromParent()
    score += 1
    updateLabels()
}

//contact with player
func contactWithPlayer(player : SKSpriteNode, enemy : SKSpriteNode) {
    enemy.removeFromParent()
    lives -= 1
    updateLabels() //another function that changes the score and lives labels
}
//CONTACT DETECTION
func didBeginContact(contact: SKPhysicsContact) {
    let firstBody : SKPhysicsBody = contact.bodyA
    let secondBody : SKPhysicsBody = contact.bodyB

    if (firstBody.categoryBitMask == PhysicsCategory.enemy && secondBody.categoryBitMask == PhysicsCategory.bullet || firstBody.categoryBitMask == PhysicsCategory.bullet && secondBody.categoryBitMask == PhysicsCategory.enemy) {
        contactWithBullet(firstBody.node as! SKSpriteNode, bullet: secondBody.node as! SKSpriteNode)
        checkScore()
        enemiesInWave -= 1
    } else if (firstBody.categoryBitMask == PhysicsCategory.enemy && secondBody.categoryBitMask == PhysicsCategory.player || firstBody.categoryBitMask == PhysicsCategory.player && secondBody.categoryBitMask == PhysicsCategory.enemy) {
        contactWithPlayer(firstBody.node as! SKSpriteNode, enemy: secondBody.node as! SKSpriteNode)
        checkLives()
        enemiesInWave -= 1
    }
}
于 2016-04-17T09:23:00.700 回答