我实现了问题中的代码“球与球的碰撞 - 检测和处理“在 Objective-C 中。然而,每当球以一定角度碰撞时,它们的速度就会急剧增加。所有向量数学都是使用 cocos2d-iphone, ,带有头 CGPointExtension.h。造成这种不期望的加速的原因是什么?

以下是速度增加的示例:

输入:
质量==12.56637
速度.x == 1.73199439
速度.y == -10.5695238

球质量 == 12.56637
球.速度.x == 6.04341078
球.速度.y == 14.2686739

输出:
质量==12.56637
速度.x == 110.004326
速度.y == -10.5695238

球质量 == 12.56637
ball.velocity.x == -102.22892
ball.velocity.y == -72.4030228

#import "CGPointExtension.h"
#define RESTITUTION_CONSTANT (0.75) //elasticity of the system

- (void) resolveCollision:(Ball*) ball
{
    // get the mtd (minimum translation distance)
    CGPoint delta = ccpSub(position, ball.position);
    float d = ccpLength(delta);
    // minimum translation distance to push balls apart after intersecting
    CGPoint mtd = ccpMult(delta, (((radius + ball.radius)-d)/d)); 


    // resolve intersection --
    // inverse mass quantities
    float im1 = 1 / [self mass]; 
    float im2 = 1 / [ball mass];

    // push-pull them apart based off their mass
    position = ccpAdd(position, ccpMult(mtd, (im1 / (im1 + im2))));
    ball.position = ccpSub(ball.position, ccpMult(mtd, (im2 / (im1 + im2))));

    // impact speed
    CGPoint v = ccpSub(velocity, ball.velocity);
    float vn = ccpDot(v,ccpNormalize(mtd));

    // sphere intersecting but moving away from each other already
    if (vn > 0.0f) return;

    // collision impulse
    float i = (-(1.0f + RESTITUTION_CONSTANT) * vn) / ([self mass] + [ball mass]);
    CGPoint impulse = ccpMult(mtd, i);


    // change in momentum
    velocity = ccpAdd(velocity, ccpMult(impulse, im1));
    ball.velocity = ccpSub(ball.velocity, ccpMult(impulse, im2));

}
有帮助吗?

解决方案

我是编写您引用的原始球弹跳代码的人。如果你 下载 并尝试该代码,您会发现它工作正常。

以下代码是正确的(与您最初的方式相同):

// collision impulse
float i = (-(1.0f + RESTITUTION_CONSTANT) * vn) / (im1 + im2);
CGPoint impulse = ccpMult(mtd, i);

这是非常常见的物理代码,您可以在以下示例中看到它几乎完全像这样实现:

这是正确的,并且它不像其他人建议的那样创建超过 1.0 的 CoR。这是根据质量和恢复系数计算相对脉冲矢量。

忽略摩擦力,一个简单的一维示例如下:

J = -Vr(1+e) / {1/m1 + 1/m2}  

其中 e 是 CoR,Vr 是归一化速度,J 是脉冲速度的标量值。

如果您打算做比这更高级的事情,我建议您使用现有的众多物理库之一。当我使用上面的代码时,对于几个球来说还可以,但是当我将其增加到数百个球时,它开始窒息。我使用了 Box2D 物理引擎,它的解算器可以处理更多的球,而且更准确。

不管怎样,我查看了你的代码,乍一看它看起来不错(这是一个非常忠实的翻译)。这可能是传入错误值的小而微妙的错误,或者向量数学问题。

我对 iPhone 开发一无所知,但我建议在该方法的顶部设置一个断点,并监视每个步骤的结果值并找到崩溃的位置。确保正确计算 MTD、冲击速度等,直到您看到大幅增加是在哪里引入的。

报告该方法中每个步骤的值,我们就会看到我们得到了什么。

其他提示

在审查原代码和原来的海报的评论,代码似乎是相同的,因此,如果原来是一个正确的实现,我会怀疑一个坏的矢量库或某种未初始化的变量的。

为什么要添加1.0〜恢复系数?

自: http://en.wikipedia.org/wiki/Coefficient_of_restitution

在COR通常是在范围[0,1]的数。定性地,1表示完全弹性碰撞,而0表示完全非弹性碰撞。大于一的COR在理论上是可能,代表产生动能的碰撞,如地雷被抛出在一起并爆炸。

另一个问题是这样的:

/ (im1 + im2)

您会受到群众的倒数之和除以相处的接触载体的冲动 - 你或许应该由群众自己的总和除以。这是您的放大冲动(“这是她说的话”)。

在此行:

CGPoint impulse = ccpMult(mtd, i);

MTD需要已被归一化。发生这个错误是因为在原来的代码MTD上一行进行归一化,但不是在你的代码。你可以做这样的事情解决它:

CGPoint impulse = ccpMult(ccpNormalize(mtd), i);
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top