基于SpriteKit中的碰撞检测更新分数的问题

时间:2018-04-28 23:07:56

标签: objective-c sprite-kit collision-detection

我正在开发一个SpriteKit游戏,其中一个场景我必须根据两个精灵之间的碰撞更新分数。每当这两个SKSpriteNodes相互碰撞时,我打算将得分增加1。 SpriteKit中有一个碰撞检测方法,它负责碰撞检测本身。我正在使用默认方法didBeginContact:检测碰撞,移除碰撞中涉及的一个对象并将得分增加1.有多个同类物体从顶部落下,并且有一个类似于篮子的物体,玩家可以移动水平地捕捉那些坠落的物体。在与篮子碰撞时,从顶部落下的物体被移除并且得分增加。问题非常简单,分数不仅增加1,而且增加2,3,4,5。这意味着它不是检测单个碰撞,而是检测到多个碰撞,因此会相应地增加分数。
我在这里看到了另一个这样的问题,但这个解决方案永远不适用于我的。在我的游戏中,有限的时间,类似的物体从顶部开始一直下降,直到时间结束。有没有办法解决这个问题。我尝试过在碰撞检测方法中使用像didCollide这样的bool变量,甚至在单独的分数增量方法中使用,但问题没有得到解决。
这是我在碰撞检测方法中尝试的代码。

-(void)didBeginContact:(SKPhysicsContact *)contact {

if (contact.bodyA.categoryBitMask == Stones) {
    [contact.bodyA.node removeFromParent];

    if (contactOccurred == NO) {
     contactOccurred = YES;
     [self updateScore:contactOccurred];
     }

}
else {
    [contact.bodyB.node removeFromParent];

    if (contactOccurred == NO) {
    ContactOccurred = YES;
    [self updateScore:contactOccurred];
     }        
  }
}  

此处是增加分数的方法的代码段。

-(void)updateScore:(BOOL)collisionOccurred {

if (collisionOccurred == YES) {

    contactOccurred = NO;
    self.score= self.score + 1;
}

}

2 个答案:

答案 0 :(得分:0)

当您使用其SKPhysicsBodies具有不规则形状的SKSpriteNodes时,它们在触摸时可以有多个接触点。这就是为什么在将Node从其父节点中删除之前,可以为相同的两个SKSpriteNodes多次调用didBeginContact

有关具有2个联系点的联系人(这会导致didBeginContact对同一两个对象调用两次),请参阅此示例:

enter image description here

要避免这种情况,您可以更改categoryBitMask中的physicsBody didBeginContact,以便不再识别以下所有联系人:

-(void)didBeginContact:(SKPhysicsContact *)contact {

    if (contact.bodyA.categoryBitMask == Stones) {
        contact.bodyA.categoryBitMask = None
        [contact.bodyA.node removeFromParent];
        self.score= self.score + 1;
    } else if (contact.bodyB.categoryBitMask == Stones) {
        contact.bodyB.categoryBitMask = None
        [contact.bodyB.node removeFromParent];
        self.score= self.score + 1;
    }       
}

显然你必须定义None位掩码值并将其从你的篮子的contactTestBitMask中排除,就像SKSpriteNode一样。这样,将您的Stone SKSpriteNode的categoryBitMaskStones更改为None后,所有其他联系人都将被忽略。

答案 1 :(得分:0)

我在阅读了Apple的文档并尝试了不同的选项后,自己解决了这个问题。问题是,作为Jorite试图在他的回答中解释的,SpriteKit提供的用于检测联系和冲突的默认方法didBeginContact方法被多次调用。但是在我的游戏中涉及碰撞的物体不是不规则的形状。一种物体是椭圆形的,而另一种物体的形状或多或少是矩形的。当两种物体接触时,这种方法被不止一次调用。

我是如何解决的?
我尝试应用Joern建议的技术,虽然我知道它不是我正在寻找的真正解决方案,而是更多的临时掩盖。但令人惊讶的是,它对我的​​游戏不起作用,因为得分仍会随机增加。我删除了我的椭圆形精灵,并用简单的圆形纯色精灵替换它们,以防万一我的椭圆形精灵在边缘附近不光滑。即使这样,问题仍然存在,导致我在此链接a link上找到Apple的文档。我开始知道,为了获得物理身体的最佳性能和更好的碰撞检测精度,我应该尽可能选择更简单的物理身体。圆形物理体是最具性能效率的,因为它的处理速度非常快,而且最简单。接下来是矩形物理体,接着是最后一个图像纹理的多边形物理体和物理体。藻类身体越复杂,计算成本越高,失去准确性的可能性就越大。我使用图像纹理创建了碰撞对象的物理实体。从纹理以某种方式创建的物理主体是(或至少在我的情况下)为什么多次调用didContactMethod的原因。甚至从纹理创建的简单圆形精灵的物理身体也会将得分增加2而不是1.我改变了代码,为我的椭圆形精灵创建了圆形的物理体,现在一切都很完美,无需更改要删除的类别节点或任何布尔标志。

通过使用布尔标志或任何其他方式避免对didBeginContact方法的多次调用可能是掩盖但不是解决方案在少数情况下有效但在其他情况下不起作用。尽可能尝试使用最简单的物理实体,尤其是当您从碰撞和接触开始获得不准确的结果时。

相关问题