SKPhysicsBody 碰撞不起作用
SKPhysicsBody Collision Not Working
下面是我的"Floor.swift"class下面基本上就是一堆墙。我有来自屏幕顶部的对象,一旦 Floor 和 SKSpriteNodes 发生碰撞,我希望 SKSpriteNode 被移除。下面是我的楼层 class.
import Foundation
import SpriteKit
class Floor: SKNode {
override init() {
super.init()
let leftWall = SKSpriteNode(color: UIColor.clear, size: CGSize(width: 5, height: 50))
leftWall.position = CGPoint(x: 0, y: 50)
leftWall.physicsBody = SKPhysicsBody(rectangleOf: leftWall.size)
leftWall.physicsBody!.isDynamic = false
self.addChild(leftWall)
let rightWall = SKSpriteNode(color: UIColor.clear, size: CGSize(width: 5, height: 50))
rightWall.position = CGPoint(x: 375, y: 50)
rightWall.physicsBody = SKPhysicsBody(rectangleOf: rightWall.size)
rightWall.physicsBody!.isDynamic = false
self.addChild(rightWall)
let bottomWall = SKSpriteNode(color: UIColor.clear, size: CGSize(width: 500, height: 10))
bottomWall.position = CGPoint(x: 150, y: -5)
bottomWall.physicsBody = SKPhysicsBody(rectangleOf: bottomWall.size)
bottomWall.physicsBody!.isDynamic = false
self.addChild(bottomWall)
self.physicsBody = SKPhysicsBody(bodies: [leftWall.physicsBody!, rightWall.physicsBody!, bottomWall.physicsBody!])
self.physicsBody?.categoryBitMask = floorCategory
self.physicsBody?.contactTestBitMask = nailDropCategory | pointCategory | lifeCategory
self.physicsBody?.collisionBitMask = balloonCategory
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemted")
}
}
GameScene class 下 "func didBegin(_ contact: SKPhysicsContact)" 我写道:
func didBegin(_ contact: SKPhysicsContact) {
if (contact.bodyA.categoryBitMask == nailDropCategory | pointCategory | lifeCategory) && (contact.bodyB.categoryBitMask == floorCategory) {
// contact.bodyB.node!.removeFromParent()
print("COLLISION")
}
}
如您所见,在我的楼层 class 中,我将对象设置为 "self.physicsBody = SKPhysicsBody(bodies:)" 以及我所有的 SKSpriteNode。但出于某种原因,我没有得到任何检测。我让我的 "Floor" class 成为我的 objectCategory、pointCategory、lifeCategory 的每个 class 上的 "contactTestBitMask"。这个问题我已经坚持了一分钟了,有什么想法吗?
更新:
所以我现在正在使用下面的这段代码,它正在运行!唯一的问题是,默认情况下也会删除我的 "balloonCategory",我不希望它这样做。我怎样才能让它只忽略那个类别,同时充当气球的墙?
func didBegin(_ contact: SKPhysicsContact) {
let contactMask = contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask
switch contactMask {
case balloonCategory | nailDropCategory:
print("nailDrop and balloon have contacted.")
contact.bodyB.node!.removeFromParent()
self.run(SKAction.playSoundFileNamed("lostlifesound.mp3", waitForCompletion:false))
lifeLost -= 1
case balloonCategory | pointCategory:
print("point and balloon have contacted.")
contact.bodyB.node!.removeFromParent()
totalPoints += 2
self.run(SKAction.playSoundFileNamed("pointsound.mp3", waitForCompletion:false))
case balloonCategory | lifeCategory:
print("life and balloon have contacted.")
contact.bodyB.node!.removeFromParent()
lifeLost += 1
self.run(SKAction.playSoundFileNamed("pointsound.mp3", waitForCompletion:false))
default:
contact.bodyB.node!.removeFromParent()
print("Removed \(String(describing: contact.bodyB.node!.name))")
}
}
你不能保证nodeB是地板,nodeA真的是nailDropCategory | pointCategory | lifeCategory
?
我假设 naildDrop
、point
和 life
是您希望在有人触摸 floor
时收到通知的 3 个对象,因此请尝试像这样构建你的 didBegin(contact:)
:
func didBegin(_ contact: SKPhysicsContact) {
print("didBeginContact entered for \(String(describing: contact.bodyA.node!.name)) and \(String(describing: contact.bodyB.node!.name))")
let contactMask = contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask
switch contactMask {
case nailDropCategory | FloorCategory:
print("nailDrop and floor have contacted.")
case pointCategory | FloorCategory:
print("point and floor have contacted.")
case lifeCategory | FloorCategory:
print("life and floor have contacted.")
default:
print("Undetected collision occurred")
}
}
你真的从你的 Floor
class 创建了一个对象吗?
听起来您会受益于为所有对象类型分配名称,如下所示:
class Balloon: SKSpriteNode {
init() {
super.init(texture: nil, color: .blue, size: CGSize(width: 50, height: 50))
self.name = "balloon"
}
}
现在,当您在开关中进行检查时,您可以在决定删除对象之前验证对象的身份。在下面的 switch 语句中查看我对 default case 所做的更改。这样,如果节点是气球,则不会被删除。物理碰撞将继续工作。
func didBegin(_ contact: SKPhysicsContact) {
let contactMask = contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask
switch contactMask {
case balloonCategory | nailDropCategory:
print("nailDrop and balloon have contacted.")
contact.bodyB.node!.removeFromParent()
self.run(SKAction.playSoundFileNamed("lostlifesound.mp3", waitForCompletion:false))
lifeLost -= 1
case balloonCategory | pointCategory:
print("point and balloon have contacted.")
contact.bodyB.node!.removeFromParent()
totalPoints += 2
self.run(SKAction.playSoundFileNamed("pointsound.mp3", waitForCompletion:false))
case balloonCategory | lifeCategory:
print("life and balloon have contacted.")
contact.bodyB.node!.removeFromParent()
lifeLost += 1
self.run(SKAction.playSoundFileNamed("pointsound.mp3", waitForCompletion:false))
default:
if contact.bodyB.node!.name == "balloon" {
print("Balloon collided but we will not remove it.")
return
} else {
contact.bodyB.node!.removeFromParent()
print("Removed \(String(describing: contact.bodyB.node!.name))")
}
}
下面是我的"Floor.swift"class下面基本上就是一堆墙。我有来自屏幕顶部的对象,一旦 Floor 和 SKSpriteNodes 发生碰撞,我希望 SKSpriteNode 被移除。下面是我的楼层 class.
import Foundation
import SpriteKit
class Floor: SKNode {
override init() {
super.init()
let leftWall = SKSpriteNode(color: UIColor.clear, size: CGSize(width: 5, height: 50))
leftWall.position = CGPoint(x: 0, y: 50)
leftWall.physicsBody = SKPhysicsBody(rectangleOf: leftWall.size)
leftWall.physicsBody!.isDynamic = false
self.addChild(leftWall)
let rightWall = SKSpriteNode(color: UIColor.clear, size: CGSize(width: 5, height: 50))
rightWall.position = CGPoint(x: 375, y: 50)
rightWall.physicsBody = SKPhysicsBody(rectangleOf: rightWall.size)
rightWall.physicsBody!.isDynamic = false
self.addChild(rightWall)
let bottomWall = SKSpriteNode(color: UIColor.clear, size: CGSize(width: 500, height: 10))
bottomWall.position = CGPoint(x: 150, y: -5)
bottomWall.physicsBody = SKPhysicsBody(rectangleOf: bottomWall.size)
bottomWall.physicsBody!.isDynamic = false
self.addChild(bottomWall)
self.physicsBody = SKPhysicsBody(bodies: [leftWall.physicsBody!, rightWall.physicsBody!, bottomWall.physicsBody!])
self.physicsBody?.categoryBitMask = floorCategory
self.physicsBody?.contactTestBitMask = nailDropCategory | pointCategory | lifeCategory
self.physicsBody?.collisionBitMask = balloonCategory
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemted")
}
}
GameScene class 下 "func didBegin(_ contact: SKPhysicsContact)" 我写道:
func didBegin(_ contact: SKPhysicsContact) {
if (contact.bodyA.categoryBitMask == nailDropCategory | pointCategory | lifeCategory) && (contact.bodyB.categoryBitMask == floorCategory) {
// contact.bodyB.node!.removeFromParent()
print("COLLISION")
}
}
如您所见,在我的楼层 class 中,我将对象设置为 "self.physicsBody = SKPhysicsBody(bodies:)" 以及我所有的 SKSpriteNode。但出于某种原因,我没有得到任何检测。我让我的 "Floor" class 成为我的 objectCategory、pointCategory、lifeCategory 的每个 class 上的 "contactTestBitMask"。这个问题我已经坚持了一分钟了,有什么想法吗?
更新:
所以我现在正在使用下面的这段代码,它正在运行!唯一的问题是,默认情况下也会删除我的 "balloonCategory",我不希望它这样做。我怎样才能让它只忽略那个类别,同时充当气球的墙?
func didBegin(_ contact: SKPhysicsContact) {
let contactMask = contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask
switch contactMask {
case balloonCategory | nailDropCategory:
print("nailDrop and balloon have contacted.")
contact.bodyB.node!.removeFromParent()
self.run(SKAction.playSoundFileNamed("lostlifesound.mp3", waitForCompletion:false))
lifeLost -= 1
case balloonCategory | pointCategory:
print("point and balloon have contacted.")
contact.bodyB.node!.removeFromParent()
totalPoints += 2
self.run(SKAction.playSoundFileNamed("pointsound.mp3", waitForCompletion:false))
case balloonCategory | lifeCategory:
print("life and balloon have contacted.")
contact.bodyB.node!.removeFromParent()
lifeLost += 1
self.run(SKAction.playSoundFileNamed("pointsound.mp3", waitForCompletion:false))
default:
contact.bodyB.node!.removeFromParent()
print("Removed \(String(describing: contact.bodyB.node!.name))")
}
}
你不能保证nodeB是地板,nodeA真的是nailDropCategory | pointCategory | lifeCategory
?
我假设 naildDrop
、point
和 life
是您希望在有人触摸 floor
时收到通知的 3 个对象,因此请尝试像这样构建你的 didBegin(contact:)
:
func didBegin(_ contact: SKPhysicsContact) {
print("didBeginContact entered for \(String(describing: contact.bodyA.node!.name)) and \(String(describing: contact.bodyB.node!.name))")
let contactMask = contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask
switch contactMask {
case nailDropCategory | FloorCategory:
print("nailDrop and floor have contacted.")
case pointCategory | FloorCategory:
print("point and floor have contacted.")
case lifeCategory | FloorCategory:
print("life and floor have contacted.")
default:
print("Undetected collision occurred")
}
}
你真的从你的 Floor
class 创建了一个对象吗?
听起来您会受益于为所有对象类型分配名称,如下所示:
class Balloon: SKSpriteNode {
init() {
super.init(texture: nil, color: .blue, size: CGSize(width: 50, height: 50))
self.name = "balloon"
}
}
现在,当您在开关中进行检查时,您可以在决定删除对象之前验证对象的身份。在下面的 switch 语句中查看我对 default case 所做的更改。这样,如果节点是气球,则不会被删除。物理碰撞将继续工作。
func didBegin(_ contact: SKPhysicsContact) {
let contactMask = contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask
switch contactMask {
case balloonCategory | nailDropCategory:
print("nailDrop and balloon have contacted.")
contact.bodyB.node!.removeFromParent()
self.run(SKAction.playSoundFileNamed("lostlifesound.mp3", waitForCompletion:false))
lifeLost -= 1
case balloonCategory | pointCategory:
print("point and balloon have contacted.")
contact.bodyB.node!.removeFromParent()
totalPoints += 2
self.run(SKAction.playSoundFileNamed("pointsound.mp3", waitForCompletion:false))
case balloonCategory | lifeCategory:
print("life and balloon have contacted.")
contact.bodyB.node!.removeFromParent()
lifeLost += 1
self.run(SKAction.playSoundFileNamed("pointsound.mp3", waitForCompletion:false))
default:
if contact.bodyB.node!.name == "balloon" {
print("Balloon collided but we will not remove it.")
return
} else {
contact.bodyB.node!.removeFromParent()
print("Removed \(String(describing: contact.bodyB.node!.name))")
}
}