【问题标题】:Filtering collisions in Chipmunk for trapped bodies在 Chipmunk 中过滤被困物体的碰撞
【发布时间】:2013-10-28 13:35:34
【问题描述】:

背景

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

问题

我最近添加了代码,以便在球相互碰撞或与墙壁碰撞时播放声音,我在 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 回调:球确实多次从墙上反弹。
  • 减小步长:物理引擎实际上需要更长的时间才能收敛。
  • 声音效果的速率限制:更好,但即使球看起来静止了,它仍然会发出噪音。

问题

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

【问题讨论】:

  • 花栗鼠不为两个接触体的第一次接触事件提供回调吗?
  • @LearnCocos2D 是的,有begin 回调,但它与separate 回调有同样的问题。顺序如下: 1) 球与墙壁碰撞。 2) 碰撞给球施加了一个推动力,导致球弹开。 3) 球和墙分开。 4) 约束求解器提供一个力将球推回墙壁,引起另一次碰撞并返回步骤 1。

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


【解决方案1】:

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

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

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

【讨论】:

  • 简单的解决方案很棒。 :-) 在每个球的基础上禁用声音而不是在整个应用程序中全局禁用声音是非常有意义的(这听起来很奇怪)。感谢您的帮助。
【解决方案2】:

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

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

【讨论】:

  • 谢谢...这些都是好主意。我将尝试使用约束的 maxForce 和碰撞斜率。
猜你喜欢
  • 1970-01-01
  • 2021-12-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-15
  • 2017-07-18
  • 1970-01-01
相关资源
最近更新 更多