func didBeginContact(contact: SKPhysicsContact) {
if ( contact.bodyA.categoryBitMask & BodyType.shield.rawValue ) == BodyType.shield.rawValue {
contact.bodyB.node?.removeFromParent()
counter++
println(counter)
} else if ( contact.bodyB.categoryBitMask & BodyType.shield.rawValue ) == BodyType.shield.rawValue {
contact.bodyA.node?.removeFromParent()
counter++
println(counter)
}
}
一个物理体来自纹理shield.physicsBody = SKPhysicsBody(texture: shieldTexture, size: shieldTexture.size())
另一个来自圈子sand.physicsBody = SKPhysicsBody(circleOfRadius: sand.size.width/2)
当拖曳物体彼此接触时,有时会多次调用sand.physicsBody = SKPhysicsBody(circleOfRadius: sand.size.width/2)
{{1}}。我如何得到它只为每个对象调用一次,即使我一接触它就从父对象中删除它。
答案 0 :(得分:2)
我已经想出如何让func didBeginContact(contact: SKPhysicsContact)
只被调用一次。这允许具有纹理SKPhysicsBody(texture: size:)
的物理体一旦计算碰撞,即使在现实中(由于纹理的物理体的性质),这个函数将被多次调用。
第1步:
为SKSpriteNode创建一个名称属性(我们将在本例中使用ball) 并将其设置为唯一名称。我们可以通过创建一个int
来做到这一点var number = 0
ball.name = "ball \(number)"
这允许创建对象的唯一名称evertime。
第2步:
创建一个数组来保存它们,将球附加到数组,增加数字
var array: [String] = []
var number = 0
ball.name = "ball \(number)"
array.append(ball.name!)
number ++
步骤3:现在在func didBeginContact(contact: SKPhysicsContact)
中查明名称是否在数组中。如果它是增加分数,则删除节点,并从阵列中删除名称。如果名称不在数组中则不做任何事情。
从数组中删除名称使我们现在只能对函数调用进行一次计数。
func didBeginContact(contact: SKPhysicsContact) {
if ( contact.bodyA.categoryBitMask & BodyType.shield.rawValue ) == BodyType.shield.rawValue {
var name = contact.bodyB.node?.name!
let index = find(array, name!)
if contains(array, name!) {
score++
contact.bodyB.node?.removeFromParent()
array.removeAtIndex(index!)
}
}
}
答案 1 :(得分:2)
在这种情况下,您可以在没有数组的情况下使其工作。而不是:
contact.bodyA.node?.removeFromParent()
counter++
使用类似的东西:
if let node = contact.bodyA.node as? SKSpriteNode {
if node.parent != nil {
node.removeFromParent()
counter++
}
}
在第一次联系时,从父项中删除节点,在后续调用中,将跳过if语句中的代码。
答案 2 :(得分:2)
使用基于纹理的物理物体时,该问题似乎更经常发生。我的解决方法是,如果在先前的碰撞触发器中指示了相同的“ contact.bodyA.node”,则禁止“ didBegin(_ contact:SKPhysicsContact)”继续。即:
if lastNodeA != contact.bodyA.node {
lastNodeA = contact.bodyA.node
...
答案 3 :(得分:1)
contactbitmask
来确定要捕获的碰撞,那么这是一个非常简单的解决方案。
只需将您不想重复检测到的对象的categoryBitMask
更新为未使用的新值,以便系统执行此操作。不再考虑后续的函数调用。
答案 4 :(得分:0)
LearnCocos2D是正确的,只要两个物体的SKphysics体接触,SKPhysicsbody didBeginContact就会连续调用,因为我们在var
中允许的形状可以有多种形式和形状。
对于那些只需要检测一次的人,我们只需要使用布尔值作为标志来检查检测是否已完成并完成。
我是这样做的:
声明var contactDone = Bool()
布尔值:
didMoveToView
在程序开始时(例如,contactDone = false
以下)
didBeginContact
检查func didBeginContact(contact:SKPhysicsBody){
if((contact.bodyA.categoryBitMask) == scoreCategory || (contact.bodyB.categoryBitMask) == scoreCategory){
if (contactDone == false){
// Increment score
score++
// Set flag to disable multiple calls by checking in didEndContact
contactDone = true
}
}
}
:
didEndContact
清除该标记,让它再次在func didEndContact(contact: SKPhysicsContact) {
if((contact.bodyA.categoryBitMask) == scoreCategory || (contact.bodyB.categoryBitMask) == scoreCategory){
if(contactDone == true){
contactDone = false
}
}
}
中检查:
SKPhysicBody(circleOfRadius: object.size.height/2)
就像我使用0F 84 FF 00 00 00
时一样。
答案 5 :(得分:0)
我的解决方案是通过Date()。timeIntervalSince1970花费时间 联系了didBegin
let passedTime = Date().timeIntervalSince1970 - lastContactTime
lastContactTime = Date().timeIntervalSince1970
if passedTime < 0.01 {
// same object
return
}