我制作了一个基础知识的游戏,如果一个精灵节点与一个墙壁发生碰撞我会失败,如果它与一个单独的节点(Ball2)相撞,你就会赢。我已经制定了如何检测碰撞,这会让你输掉比赛,但是当球与球2碰撞时却没有。所以我的问题是如何进行两种不同的碰撞,使不同的事情发生? 我真的很想得到一些帮助,谢谢
struct PhysicsCategogy {
static let Ball : UInt32 = 0x1 << 1
static let Ball2 : UInt32 = 0x1 << 1
static let WallH : UInt32 = 0x1 << 2
static let WallH2 : UInt32 = 0x1 << 3
}
class GameScene: SKScene, SKPhysicsContactDelegate {
var Ball = SKSpriteNode(imageNamed: "Ball")
var Ball2 = SKSpriteNode(imageNamed: "Ball")
var WallH = SKSpriteNode(imageNamed: "WallH")
override func didMoveToView(view: SKView) {
self.view?.paused = false
self.physicsWorld.gravity = CGVector(dx: 0, dy: 0)
self.physicsWorld.contactDelegate = self
Ball.position = CGPointMake(self.frame.width / 2 - 450, self.frame.height / 2)
Ball.setScale(0.5)
Ball.physicsBody = SKPhysicsBody(rectangleOfSize: Ball.size)
Ball.physicsBody?.affectedByGravity = false
Ball.physicsBody?.dynamic = true
Ball.physicsBody?.contactTestBitMask = PhysicsCategogy.Ball
Ball.physicsBody?.collisionBitMask = 0
Ball.physicsBody?.collisionBitMask = 2
addChild(Ball)
Ball2.position = CGPointMake(self.frame.width / 2 + 450, self.frame.height / 2)
Ball2.setScale(0.5)
Ball2.physicsBody = SKPhysicsBody(rectangleOfSize: Ball.size)
Ball2.physicsBody?.affectedByGravity = false
Ball2.physicsBody?.dynamic = true
Ball2.physicsBody?.contactTestBitMask = PhysicsCategogy.Ball2
Ball2.physicsBody?.collisionBitMask = 1
addChild(Ball2)
WallH.position = CGPointMake(self.frame.width / 2, self.frame.height / 2 + 190)
WallH.setScale(7.5)
WallH.physicsBody = SKPhysicsBody(rectangleOfSize: WallH.size)
WallH.physicsBody?.affectedByGravity = false
WallH.physicsBody?.contactTestBitMask = PhysicsCategogy.WallH
WallH.physicsBody?.collisionBitMask = 0
self.addChild(WallH)
}
func didBeginContact(contact: SKPhysicsContact) {
self.backgroundColor = SKColor.whiteColor()
self.view?.paused = true
}
}
答案 0 :(得分:3)
你的代码中有很多东西是错误的......首先,你必须从拼写错误和冗余代码中清理你的项目,例如这没有意义:
Ball.physicsBody?.collisionBitMask = 0 //Remove it
Ball.physicsBody?.collisionBitMask = 2
现在让我们从头开始。您错误地设置了物理类别。你想要这样的东西:
struct PhysicsCategory {
static let Ball : UInt32 = 1 << 0 //1
static let Ball2 : UInt32 = 1 << 1 //2
static let WallH : UInt32 = 1 << 2 //4
static let WallH2 : UInt32 = 1 << 3 //8
}
接下来的事情是,如何正确设置类别,碰撞和接触位掩码。你不想要这个:
Ball.physicsBody?.contactTestBitMask = PhysicsCategory.Ball
这没有任何意义,因为屏幕上只有Ball
的一个实例。您想要检测Ball
和Ball2
之间的联系人,如下所示:
Ball.physicsBody?.contactTestBitMask = PhysicsCategory.Ball2
因此,我们可以正确设置所有内容(请注意,您根本没有设置Ball categoryBitMask
):
Ball.physicsBody?.categoryBitMask = PhysicsCategory.Ball
Ball.physicsBody?.contactTestBitMask = PhysicsCategory.Ball2
Ball.physicsBody?.collisionBitMask = PhysicsCategory.Ball2
在这里,您将Ball的类别设置为PhysicsCategory.Ball
,并将其接触和碰撞位掩码设置为PhysicsCategory.Ball2
。您这样做是因为您想要检测联系人并在这两个主体之间发生冲突。同样适用于Ball2
:
Ball2.physicsBody?.categoryBitMask = PhysicsCategogy.Ball2
Ball2.physicsBody?.contactTestBitMask = PhysicsCategogy.Ball
Ball2.physicsBody?.collisionBitMask = PhysicsCategogy.Ball
您也可以将相同的逻辑应用于墙壁。例如,如果你想在球和墙之间发生碰撞,但是你不想在发生碰撞时注册联系人(意思是,你不想要didBeginContact
被调用),你会做这样的事情(假设为每个身体正确设置categoryBitMask
):
//You don't want to register contacts between Ball and a WallH
Ball.physicsBody?.contactTestBitMask = PhysicsCategory.Ball2
//But still, you want collisions with Ball2 and a WallH
Ball.physicsBody?.collisionBitMask = PhysicsCategory.Ball2 | PhysicsCategory.WallH
//You don't want to register contacts between Ball2 and a WallH
Ball2.physicsBody?.contactTestBitMask = PhysicsCategory.Ball
//But still, you want collisions with Ball and a WallH
Ball2.physicsBody?.collisionBitMask = PhysicsCategory.Ball | PhysicsCategory.WallH
WallH.physicsBody?.collisionBitMask = PhysicsCategory.Ball | PhysicsCategory.Ball2
请确保您了解术语联系和碰撞之间的区别。即使禁用了碰撞(collisionBitMask = 0
),也可能发生联系,反之亦然。这取决于您如何设置接触/碰撞位掩码。你可以在SpriteKit中选择你想要使用的物理引擎的哪个部分。接触检测,物理模拟或两者。如果您对接触检测不感兴趣,则不应因性能原因设置接触面罩。
最后,要处理联系人,您可以使用以下内容:
func didBeginContact(contact: SKPhysicsContact) {
var firstBody, 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 & PhysicsCategory.Ball) != 0 &&
(secondBody.categoryBitMask & PhysicsCategory.Ball2 != 0)) {
//firstBody is a Ball
//secondBody is a Ball2
print ("Detected contact between Ball and a Ball2")
}
}
如果您想更多地了解代码的某些部分,例如self.physicsWorld.contactDelegate = self
或didBeginContact
的调用方式,请查看this。
对于我刚刚为您写的内容有点不同的实现,但是如何完成相同的事情的一个很好的例子,请看看this。
但最后,官方docs总是一个好的开始,或者如果你不确定任何事情就回来。
答案 1 :(得分:1)
你需要有一些对于所有可以碰撞的对象都是通用的字段,在这种情况下,可以作为类型标识符的墙和球。然后,当您处理碰撞时,您需要检查该字段是否有条件说明&#34;如果它是墙,做丢失的东西,否则如果它是一个球,做获胜的东西&#34;