0

背景

  • 我正在为孩子们制作一个 iOS 应用程序,您可以在其中用手指在屏幕上拖动球。
  • 我正在使用 Chipmunk 7.0.0 进行物理模拟。
  • 我已经修改了Chipmunk 演示代码来实现拖动功能。
  • 我正在使用 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也是如此,这听起来很糟糕。看起来球正在从墙上弹起,被约束推回墙上,冲洗并重复。在这种情况下,我只想播放一次或两次碰撞声音。

我尝试过的东西似乎不起作用...

  • cpArbiterTotalKE使用、或相对速度进行过滤cpArbiterTotalImpulse:冲量、动能和相对速度都在典型碰撞的范围内。
  • 使用separate回调:球确实多次从墙上反弹。
  • 减小步长:物理引擎实际上需要更长的时间来收敛。
  • 限制声音效果的速率:更好,但即使在看起来静止后,球仍然会发出噪音。

问题

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

4

2 回答 2

1

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

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

在 cocos2d-iphone 中,您可以添加一个更新方法的 deltaTime 来跟踪时间。还有多种获取系统时间的方法,例如,[NSDate date].timeIntervalSince1970为您提供自 1970 年以来的当前秒数。我知道,这似乎很荒谬,但如果您稍后再次获得该数字,并减去之前的秒数,您将得到以秒为单位的差异,这就是最重要的。

于 2013-10-28T16:59:26.707 回答
1

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

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

于 2013-10-28T17:10:20.533 回答