过滤Chipmunk中的被困物体碰撞

时间:2013-10-28 13:35:35

标签: ios objective-c cocos2d-iphone chipmunk simpleaudioengine

背景

  • 我正在为孩子们制作iOS应用,你可以用手指在屏幕上拖动球。
  • 我正在使用Chipmunk 7.0.0进行物理模拟。
  • 我已调整Chipmunk demo code来实现拖动功能。
  • 我正在使用2 ms固定时间步。 (这不像我的应用程序有更好的事情......)

问题

我最近添加了代码来播放声音,只要球相互碰撞或与墙碰撞,我正在postSolve回调中进行:

static void postSolve(cpArbiter *arb, cpSpace *space, cpDataPointer userData)
{
    GameLayer *layer = (__bridge GameLayer *)userData;
    [layer collisionHandler:arb];
}

-(void) collisionHandler:(cpArbiter*)arb
{
    if(cpArbiterIsFirstContact(arb)) {
        [[SimpleAudioEngine sharedEngine] playEffect:kCollisionEffectFilename];
    }
}

问题在于......当我将球拖入墙壁时,即使在cpArbiterIsFirstContact上进行过滤,也会产生大量的碰撞,这听起来很糟糕。似乎球从墙上反弹,被约束驱赶回墙壁,冲洗并重复。在这种情况下,我只想播放一次或两次碰撞声。

我尝试过的似乎不起作用的事情......

  • 使用cpArbiterTotalKEcpArbiterTotalImpulse或相对速度进行过滤:脉冲,动能和相对速度均在典型碰撞范围内。
  • 使用separate回调:球真的多次从墙上反弹。
  • 减小步长:物理引擎实际上需要更长时间才能收敛。
  • 限制声音效果的速度:更好,但即使看起来它静止不动,球仍然会产生噪音。

问题

有没有办法过滤被困物体的碰撞?

2 个答案:

答案 0 :(得分:1)

一个简单而有效的解决方案是避免快速连续播放声音。

当球与墙壁接触时,检查球的“最后接触”计时器是否低于当前时间。如果是这样,播放声音并将球的“最后接触”时间设置为当前时间加x,其中x是声音不应再次播放的超时持续时间(即0.5秒)。

在cocos2d-iphone中,您可以添加更新方法的deltaTime来跟踪时间。还有很多方法可以获得系统时间,例如[NSDate date].timeIntervalSince1970给出了自1970年以来的当前秒数。我知道,这看起来很荒谬,但是如果你以后再次获得这个数字,并减去之前的数字只需几秒钟即可获得差异,这就是重要的。

答案 1 :(得分:1)

所以你使用约束来拖动球,球是否有弹性?您是否尝试过调整约束参数?如果约束具有较低的maxForce,则振荡的可能性将显着下降。

另一件可以帮助的事情是增加空间的碰撞斜率(允许多少形状重叠)。默认值为0.1(无论您使用的是什么比例),但将其增加到像素左右可以显着帮助这种事情,而不会非常明显。