Objective c SKPhysicsContact有没有办法确定哪个物体是A和B?
在SpriteKit中,我们通过didBeginContact方法检测到了。 但这样做看起来有点愚蠢: func didBeginContact(联系人:SKPhysicsContact){Objective c SKPhysicsContact有没有办法确定哪个物体是A和B?,objective-c,swift,sprite-kit,game-physics,Objective C,Swift,Sprite Kit,Game Physics,在SpriteKit中,我们通过didBeginContact方法检测到了。 但这样做看起来有点愚蠢: func didBeginContact(联系人:SKPhysicsContact){ 是否有任何方法可以确保bodyA始终是一个球?是否有任何与categorybitmask相关的规则?如果使用简单的类别,每个物理体只属于一个类别,那么didBeginContact的这种替代形式可能更具可读性: func didBeginContact(contact: SKPhysicsContact)
是否有任何方法可以确保bodyA始终是一个球?是否有任何与categorybitmask相关的规则?如果使用简单的类别,每个物理体只属于一个类别,那么didBeginContact的这种替代形式可能更具可读性:
func didBeginContact(contact: SKPhysicsContact) {
let contactMask = contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask
switch contactMask {
case categoryBitMask.ball | categoryBitMask.something:
print("Collision between ball and something")
let ballNode = contact.bodyA.categoryBitMask == categoryBitMask.ball ? contact.bodyA.node! : contact.bodyB.node!
ballNode.pop()
score += 10
default :
//Some other contact has occurred
print("Some other contact")
}
}
请注意,如果您的类别更复杂,这将无法像简单测试那样工作,并且测试(
categoryBitMask.ball | categoryBitMask.something
)将不匹配。通常您会这样做
首先,如果您还没有存储位掩码类别,则需要存储位掩码类别
enum PhysicsCategory {
static let ball: UInt32 = 0x1 << 0
static let wall: UInt32 = 0x1 << 1
static let enemy: UInt32 = 0x1 << 2
}
注意:因为在本例中,球会同时检查与墙和敌人的接触,所以您不需要告诉墙或敌人检查与球的接触。
在1物理体上执行此操作很好,因此您可以在其他物理体上将其设置为0,除非他们有其他特定联系人要查找
然后,您可以像这样在contact方法中检查它们,而无需使用double if语句
func didBegin(_ contact: SKPhysicsContact) {
let firstBody: SKPhysicsBody
let secondBody: SKPhysicsBody
if contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask {
firstBody = contact.bodyA
secondBody = contact.bodyB
} else {
firstBody = contact.bodyB
secondBody = contact.bodyA
}
// Ball hit wall or wall hit ball
if (firstBody.categoryBitMask == PhysicsCategory.ball) && (secondBody.categoryBitMask == PhysicsCategory.wall) {
// Some code
}
// Ball hit enemy or enemy hit ball
if (firstBody.categoryBitMask == PhysicsCategory.ball) && (secondBody.categoryBitMask == PhysicsCategory.enemy) {
// Some code
}
}
希望这有助于在多个联系人同时出现的情况下,此代码在某些情况下可能会崩溃。假设您有三个对象相交。SpriteKit一次只能处理一个联系人。并假设您正在删除对象(类型)当父对象A与类型B或C的对象接触时,它将从父对象A中删除。因此将调用两次didBeginContact。如果从其父对象A中删除对象A,则在下一次didBeginContact调用中,强制展开将失败。您应该指示他不要像这样使用强制展开,因为节点属性可能为零……否则,它应该可以工作,并且它是无效的可读:)@Whirlwind这是否意味着
如果let
和guard
在这里有用?@困惑最像是let或guard是的。甚至是可选的链接。只是为了防止潜在的崩溃。这可能会发生……我(最近)开始了解如何以及为什么要使用if let
,还没有时间去弄清楚如何保护
。但是我喜欢玩物理引擎,所以这看起来是一个很好的借口,可以找到如何在合理的位置有目的地使用它。谢谢!!!我深入研究了SKTemplate对if let
的使用copy()
SKShapeNodes
。当我意识到它真的在做两件事时,这是一个富有洞察力的时刻。1.将一个可选项转换为一个同名的实际项,2.提供一个在一个范围内做一系列事情的机会。我仍然在外面吃午饭,讨论关闭该范围内的某些内容的好处,正如S的回答中所发生的那样teve,其中我为ballNode赋值放置了一个if-let
,它将包装pop()调用并添加到score变量。在这种情况下,这是使用if-let
的正确位置/想法吗?
ball.physicsBody?.categoryBitMask = PhysicsCategory.ball
ball.physicsBody?.contactTestBitMask = PhysicsCategory.wall | PhysicsCategory.enemy
wall.physicsBody?.categoryBitMask = PhysicsCategory.wall
wall.physicsBody?.contactTestBitMask = 0
enemy.physicsBody?.categoryBitMask = PhysicsCategory.enemy
enemy.physicsBody?.contactTestBitMask = 0
func didBegin(_ contact: SKPhysicsContact) {
let firstBody: SKPhysicsBody
let secondBody: SKPhysicsBody
if contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask {
firstBody = contact.bodyA
secondBody = contact.bodyB
} else {
firstBody = contact.bodyB
secondBody = contact.bodyA
}
// Ball hit wall or wall hit ball
if (firstBody.categoryBitMask == PhysicsCategory.ball) && (secondBody.categoryBitMask == PhysicsCategory.wall) {
// Some code
}
// Ball hit enemy or enemy hit ball
if (firstBody.categoryBitMask == PhysicsCategory.ball) && (secondBody.categoryBitMask == PhysicsCategory.enemy) {
// Some code
}
}
physicsWorld.contactDelegate = self