我正在使用 SpriteKit 在 XCode 中制作游戏。该游戏有一个玩家和他必须避免的不同类型的射弹。当玩家与弹丸发生碰撞时,分数会发生变化并且弹丸会消失。然而,当两个射弹相撞时,它们会弹开。 我想让每次两颗射弹碰撞时,它们都像什么都没发生过一样,继续沿着原来的路径前进。我该怎么办?
*注意:这不是全部代码,它只是重要的部分。
import SpriteKit
struct Physics {
static let player : UInt32 = 1
static let missileOne : UInt32 = 2
static let missileTwo : UInt32 = 3
}
class GameScene: SKScene, SKPhysicsContactDelegate {
var player = SKSpriteNode(imageNamed: "p1.png")
override func didMoveToView(view: SKView) {
physicsWorld.contactDelegate = self
player.position = CGPointMake(self.size.width/2, self.size.height/5)
player.physicsBody = SKPhysicsBody(rectangleOfSize: player.size)
player.physicsBody?.affectedByGravity = false
player.physicsBody?.dynamic = false
player.physicsBody?.categoryBitMask = Physics.player
player.physicsBody?.collisionBitMask = Physics.missileOne
player.physicsBody?.collisionBitMask = Physics.missileTwo
var missileOneTimer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: Selector("SpawnMissileOne"), userInfo: nil, repeats: true)
var missileTwoTimer = NSTimer.scheduledTimerWithTimeInterval(1.2, target: self, selector: Selector("SpawnMissileTwo"), userInfo: nil, repeats: true)
self.addChild(player)
}
//When contact happens
func didBeginContact(contact: SKPhysicsContact) {
var firstBody : SKPhysicsBody = contact.bodyA
var secondBody : SKPhysicsBody = contact.bodyB
if ((firstBody.categoryBitMask == Physics.player) && (secondBody.categoryBitMask == Physics.missileOne)) {
CollisionWithMissileOne(firstBody.node as SKSpriteNode, missileOne: secondBody.node as SKSpriteNode)
} else if ((firstBody.categoryBitMask == Physics.player) && (secondBody.categoryBitMask == Physics.missileTwo)){
CollisionWithMissileTwo(firstBody.node as SKSpriteNode, missileTwo: secondBody.node as SKSpriteNode)
} else if ((firstBody.categoryBitMask == Physics.missileOne)&&(secondBody.categoryBitMask == Physics.missileTwo)) {
CollisionBetweenMissiles(firstBody.node as SKSpriteNode, missileTwo: secondBody.node as SKSpriteNode)
}
}
//For Player and MissileOne
func CollisionWithMissileOne(player: SKSpriteNode, missileOne: SKSpriteNode) {
missileOne.removeFromParent()
}
//For Player and MissileTwo
func CollisionWithMissileOne(player: SKSpriteNode, missileTwo: SKSpriteNode) {
missileTwo.removeFromParent()
}
//For MissileOne and MissileTwo
func CollisionBetweenMissiles(missileOne: SKSpriteNode, missileTwo: SKSpriteNode) {
???WHAT SHOULD I CODE HERE???
}
}
最佳答案
混淆是 collisionBitMask
用于定义在 physicsModel 中交互的 physicsBodies。您真正想要的是 contactTestBitmask
。
此外,您的 Physics 不会返回用于位掩码的正确值。作为纯整数,它们应该是 1、2、4、8 等。
这是您的代码已更改为(希望)有效的代码,无论我在哪里进行更改,我都对它们进行了评论。
struct Physics {
static let player : UInt32 = 1
static let missileOne : UInt32 = 2
static let missileTwo : UInt32 = 4 // to work properly as bit masks
}
如果您想检查与一种以上类型的 physicsBody.categoryBitMask 的联系,则必须进行此更改。查看 didMoveToView 中的 player.physicsBody?.contactTestBitMask = ...
:
override func didMoveToView(view: SKView) {
physicsWorld.contactDelegate = self
// All your existing player-stuff is fine until...
// contactTest, not collision but contact, also: use bitwise OR
player.physicsBody?.contactTestBitMask = Physics.missileOne | Physics.missileTwo
self.addChild(player)
// It is not recommended to use NSTimer for SpriteKit, use SKActions instead
let missileOneWait = SKAction.waitForDuration(1)
let callSpawnOneAction = SKAction.runBlock({ self.spawnMissileOne() })
let missileOneRepeat = SKAction.repeatActionForever(SKAction.sequence([missileOneWait, callSpawnOneAction]))
runAction(missileOneRepeat)
let missileTwoWait = SKAction.waitForDuration(1.2)
let callSpawnTwoAction = SKAction.runBlock({ self.spawnMissileTwo() })
let missileTwoRepeat = SKAction.repeatActionForever(SKAction.sequence([missileTwoWait, callSpawnTwoAction]))
runAction(missileTwoRepeat)
}
几乎将 didBeginContact 重写为我认为阅读和缩放更好的东西:
func didBeginContact(contact: SKPhysicsContact) {
var firstBody = contact.bodyA
var secondBody = contact.bodyB
// Rewritten with dynamic variables
var playerNode : SKSpriteNode? {
if firstBody.categoryBitMask == Physics.player {
return firstBody.node as? SKSpriteNode
} else if secondBody.categoryBitMask == Physics.player {
return secondBody.node as? SKSpriteNode
}
return nil
}
// If you want to handle contact between missiles you need to split this
// into two different variables
var missileNode : SKSpriteNode? {
let bitmask1 = firstBody.categoryBitMask
let bitmask2 = secondBody.categoryBitMask
if bitmask1 == Physics.missileOne || bitmask1 == Physics.missileTwo {
return firstBody.node as? SKSpriteNode
} else if bitmask2 == Physics.missileOne || bitmask2 == Physics.missileTwo {
return secondBody.node as? SKSpriteNode
}
return nil
}
if playerNode != nil {
collisionBetweenPlayer(playerNode, missile: missileNode)
}
}
那么你只需要一个函数来实现导弹和玩家之间的联系:
func collisionBetweenPlayer(player: SKSpriteNode?, missile: SKSpriteNode?) {
missile?.removeFromParent()
}
关于ios - SpriteKit 中 Sprite 之间的碰撞,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32446973/