class GameScene: SKScene, SKPhysicsContactDelegate {
let balls = [
SKSpriteNode(imageNamed: "blueball.png"),
SKSpriteNode(imageNamed: "greenball.png"),
SKSpriteNode(imageNamed: "realredball.png"),
]
let redRectangle = SKSpriteNode(imageNamed: "redrectangle.png")
let blueRectangle = SKSpriteNode(imageNamed: "bluerectangle.png")
let greenRectangle = SKSpriteNode(imageNamed: "greenrectangle.png")
let blueBallCategory: UInt32 = 0x1 << 0
let greenBallCategory: UInt32 = 0x1 << 1
let realRedBallCategory: UInt32 = 0x1 << 2
let redRectangleCategory: UInt32 = 0x1 << 3
let blueRectangleCategory: UInt32 = 0x1 << 4
let greenRectangleCategory: UInt32 = 0x1 << 5
override func didMove(to view: SKView) {
spawnBallsandRectangles()
physicsWorld.contactDelegate = self
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
physics()
}
func didBegin(_ contact: SKPhysicsContact) {
var firstBody: SKPhysicsBody
var secondBody: SKPhysicsBody
if contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask {
firstBody = contact.bodyA
secondBody = contact.bodyB
} else {
firstBody = contact.bodyB
secondBody = contact.bodyA
}
if firstBody.categoryBitMask == blueBallCategory
&& secondBody.categoryBitMask == redRectangleCategory {
print("dead")
}
}
func spawnBallsandRectangles() {
let ball = balls[Int(arc4random_uniform(UInt32(balls.count)))]
ball.position = CGPoint(x: 0, y: 250)
ball.size = CGSize(width: 70, height: 70)
balls[0].physicsBody?.categoryBitMask = blueBallCategory
balls[1].physicsBody?.categoryBitMask = greenBallCategory
balls[2].physicsBody?.categoryBitMask = realRedBallCategory
balls[0].physicsBody?.contactTestBitMask = redRectangleCategory
redRectangle.position = CGPoint(x: 0, y: -600)
redRectangle.size = CGSize(width: 200, height: 20)
redRectangle.physicsBody?.categoryBitMask = redRectangleCategory
blueRectangle.position = CGPoint(x: -200, y: -600)
blueRectangle.size = CGSize(width: 200, height: 20)
blueRectangle.physicsBody?.categoryBitMask = blueRectangleCategory
greenRectangle.position = CGPoint(x: 200, y: -600)
greenRectangle.size = CGSize(width: 200, height: 20)
greenRectangle.physicsBody?.categoryBitMask = greenRectangleCategory
self.addChild(ball)
self.addChild(redRectangle)
self.addChild(blueRectangle)
self.addChild(greenRectangle)
}
func physics() {
for ball in balls {
ball.physicsBody = SKPhysicsBody(circleOfRadius: ball.size.height/2)
}
redRectangle.physicsBody = SKPhysicsBody(rectangleOf: redRectangle.size)
redRectangle.physicsBody?.affectedByGravity = false
redRectangle.physicsBody?.isDynamic = false
blueRectangle.physicsBody = SKPhysicsBody(rectangleOf: redRectangle.size)
blueRectangle.physicsBody?.affectedByGravity = false
greenRectangle.physicsBody = SKPhysicsBody(rectangleOf: redRectangle.size)
greenRectangle.physicsBody?.affectedByGravity = false
}
}
我希望蓝色球(ball[0]
)能够点击redRectangle
节点并触发碰撞检测。我对它进行了编程,这样当蓝色球落在红色矩形上时,如果检测到碰撞,控制台将print ("dead")
。它没有做到这一点。
注意:蓝色,红色或绿色球从屏幕顶部落下并落在蓝色,红色或绿色矩形上。但到目前为止,我只为蓝色球和红色矩形设置了检测碰撞代码。我希望有人可以提供帮助,非常感谢。
答案 0 :(得分:0)
问题是您要为方法SKPhysicsBody
中的节点分配physics()
。方法spawnBallsandRectangles()
将值分配给这些实体的categoryBitMask
属性。由于您在spawnBallsandRectangles()
之前调用了physics()
,因此这些实体尚不存在,并且位掩码的分配失败。
我会将所有设置代码从physics()
移动到spawnBallsandRectangles()
,以便您可以在尝试为其属性指定值之前设置物理主体。要让球保持静止直到触摸,您可以使用self.isPaused = true
暂停场景,然后稍后使用self.isPaused = false
重新开始,或者使用球上的isDynamic
属性,这样它们就不会动态直到感动。
您可以使用此技术来检测触摸的球,然后在触摸后使其动态化:How do I detect if an SKSpriteNode has been touched
我使用最后一种技术重新编写代码来演示。
class GameScene: SKScene, SKPhysicsContactDelegate {
let balls = [
SKSpriteNode(imageNamed: "blueball.png"),
SKSpriteNode(imageNamed: "greenball.png"),
SKSpriteNode(imageNamed: "realredball.png"),
]
let redRectangle = SKSpriteNode(imageNamed: "redrectangle.png")
let blueRectangle = SKSpriteNode(imageNamed: "bluerectangle.png")
let greenRectangle = SKSpriteNode(imageNamed: "greenrectangle.png")
let blueBallCategory: UInt32 = 0x1 << 0
let greenBallCategory: UInt32 = 0x1 << 1
let realRedBallCategory: UInt32 = 0x1 << 2
let redRectangleCategory: UInt32 = 0x1 << 3
let blueRectangleCategory: UInt32 = 0x1 << 4
let greenRectangleCategory: UInt32 = 0x1 << 5
override func didMove(to view: SKView) {
// set up all properties for balls and rectangles
spawnBallsandRectangles()
self.physicsWorld.contactDelegate = self
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
// find node touched
guard let touched = touches.first else { return }
let position = touched.location(in: self)
let touchedNode = self.atPoint(position)
// if it's a ball then start it falling
if touchedNode.name == "ball" {
touchedNode.physicsBody?.isDynamic = true
}
}
func didBegin(_ contact: SKPhysicsContact) {
var firstBody: SKPhysicsBody
var secondBody: SKPhysicsBody
if contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask {
firstBody = contact.bodyA
secondBody = contact.bodyB
} else {
firstBody = contact.bodyB
secondBody = contact.bodyA
}
if firstBody.categoryBitMask == blueBallCategory
&& secondBody.categoryBitMask == redRectangleCategory {
print("dead")
}
}
/// Convenience method to set up the rectangles
static func setupRectangle(rectangle: SKSpriteNode,
category: UInt32,
position: CGPoint) {
rectangle.position = position
rectangle.size = CGSize(width: 200, height: 20)
let physicsBody = SKPhysicsBody(rectangleOf: rectangle.size)
physicsBody.affectedByGravity = false
physicsBody.isDynamic = false
physicsBody.categoryBitMask = category
rectangle.physicsBody = physicsBody
}
func spawnBallsandRectangles() {
for ball in balls {
// name them to later identify them when touched
ball.name = "ball"
// give it a physics body and freeze it
let physicsBody = SKPhysicsBody(circleOfRadius: ball.size.height/2)
physicsBody.isDynamic = false
ball.physicsBody = physicsBody
}
let ball = balls[Int(arc4random_uniform(UInt32(balls.count)))]
ball.position = CGPoint(x: 0, y: 250)
ball.size = CGSize(width: 70, height: 70)
balls[0].physicsBody?.categoryBitMask = blueBallCategory
balls[1].physicsBody?.categoryBitMask = greenBallCategory
balls[2].physicsBody?.categoryBitMask = realRedBallCategory
balls[0].physicsBody?.contactTestBitMask = redRectangleCategory
GameScene.setupRectangle(rectangle: redRectangle,
category: redRectangleCategory,
position: CGPoint(x: 0, y: -600))
GameScene.setupRectangle(rectangle: blueRectangle,
category: blueRectangleCategory,
position: CGPoint(x: -200, y: -600))
GameScene.setupRectangle(rectangle: greenRectangle,
category: greenRectangleCategory,
position: CGPoint(x: 200, y: -600))
self.addChild(ball)
self.addChild(redRectangle)
self.addChild(blueRectangle)
self.addChild(greenRectangle)
}
}