如何使两种不同的碰撞发生不同的事情?
How to make two different collisions which makes different things happen?
我制作了一个游戏,其中的基础知识是,如果一个精灵节点与我松开的墙碰撞,如果它与一个单独的节点(Ball2)碰撞,你就会赢。我已经做了如何检测让你输掉比赛的碰撞,但不是当 Ball 与 ball2 碰撞时。所以我的问题是如何进行两种不同的碰撞,从而使不同的事情发生?
我真的很想得到一些帮助,谢谢
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
}
}
您需要有一些对所有 "collidable" 对象通用的字段,在这种情况下,包括墙和球,可以充当类型标识符。然后,当您处理碰撞时,您需要使用 "if it's a wall, do stuff for losing, else if it's a ball, do stuff for winning"
条件检查该字段
您的代码中有很多地方是错误的...首先,您必须清除您的项目中的拼写错误和冗余代码,例如,这是没有意义的:
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
为每个 body 设置正确):
//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
) 也可能发生接触,反之亦然。这取决于您如何设置 contact/collision 位掩码。你可以在 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.
但最后,官方 docs 始终是一个很好的起点,或者如果您不确定任何事情可以回来。
我制作了一个游戏,其中的基础知识是,如果一个精灵节点与我松开的墙碰撞,如果它与一个单独的节点(Ball2)碰撞,你就会赢。我已经做了如何检测让你输掉比赛的碰撞,但不是当 Ball 与 ball2 碰撞时。所以我的问题是如何进行两种不同的碰撞,从而使不同的事情发生? 我真的很想得到一些帮助,谢谢
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
}
}
您需要有一些对所有 "collidable" 对象通用的字段,在这种情况下,包括墙和球,可以充当类型标识符。然后,当您处理碰撞时,您需要使用 "if it's a wall, do stuff for losing, else if it's a ball, do stuff for winning"
条件检查该字段您的代码中有很多地方是错误的...首先,您必须清除您的项目中的拼写错误和冗余代码,例如,这是没有意义的:
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
为每个 body 设置正确):
//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
) 也可能发生接触,反之亦然。这取决于您如何设置 contact/collision 位掩码。你可以在 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
的调用方式,请查看
但最后,官方 docs 始终是一个很好的起点,或者如果您不确定任何事情可以回来。