我正在尝试制作一款简单的太空射击游戏。这种接触应该发生在鱼雷和外星人之间,或者航天飞机和外星人之间。问题是,第二次接触(航天飞机对外星人)只发生在第一次接触(鱼雷对外星人)之后,而且它们并不总是精确的。这是在类之外创建的结构
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。提前谢谢!
您可能会发现如下重组didBeginContact
不那么令人困惑,因为这避免了第一个身体/第二个身体的东西和复杂的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
我建议您阅读有关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
希望这能有所帮助。
所以我昨天确实解决了我的问题。我正在发布更新后的代码,以防它能帮助到别人。课外:
struct PhysicsCategory {
static let player : UInt32 = 0x1 << 0
static let bullet : UInt32 = 0x1 << 1
static let enemy : UInt32 = 0x1 << 2}
然后,在像我之前写的那样将phyics应用到每个精灵之后,在类内:
//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
}
}