2009-05-21 89 views
4

我在Objective-C中实现了问题“Ball to Ball Collision - Detection and Handling”中的代码。但是,每当球以一定角度碰撞时,其速度就会急剧增加。所有的矢量数学运算使用cocos2d-iphone,头CGPointExtension.h完成。这种不希望的加速度的原因是什么?球对球碰撞 - 在碰撞时获得显着的速度

以下是在速度增加的一个示例:

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

球.mass == 12.56637
ball.velocity.x == 6.04341078
ball.velocity.y == 14.2686739

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

ball.mass == 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)); 

} 
+0

你的物理是这里的问题:您正在设置不节约动能的碰撞,因为恢复系数为1.75(超过1)。 因此,这不是一个编程相关的错误。 – jpinto3912 2009-05-21 21:03:44

+0

你可以发布你的代码有效的最终版本吗? – 2009-05-21 22:45:04

回答

3

我是写下你引用的原始球跳动代码的人。如果你download并尝试该代码,你可以看到它工作正常。

下面的代码是正确的(你的方式原本是):

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

这是很常见的物理代码,你可以看到它几乎完全一样实现在下面的例子:

这是正确的,它不〜像其他人建议的那样,创建一个超过1.0的CoR。这是计算基于质量和恢复系数的相对脉冲向量。

忽略的摩擦,一个简单的例子1D是如下:

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

其中E是COR,Vr为你的归一化速度和J是脉冲速度的标量值。

如果你打算做比这更高级的任何事情,我建议你使用已经存在的许多物理库之一。当我使用上面的代码时,对于几个球来说很好,但是当我将它升高到几百个时,它开始窒息。我已经使用了Box2D物理引擎,其解算器可以处理更多的球,并且它更准确。

无论如何,我看了你的代码,乍一看它看起来很好(这是一个非常忠实的翻译)。这可能是一个错误的价值被传入的一个小而细微的错误,或向量数学问题。

我不知道任何关于iPhone的发展,但我会建议在该方法的顶部设置一个断点,并监视每个步骤产生的价值,并找出爆炸的地方。确保正确计算MTD,冲击速度等等,直到你看到引入大幅增加的位置。

回报该方法中每个步骤的值,我们会看到我们拥有的。

5

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

为什么你给恢复系数加1.0?

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

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

另一个问题是这样的:

/ (im1 + im2) 

你受到了群众的倒数之和除以相处的接触载体的冲动 - 你可能应该由群众的总和除以他们自己。这是放大你的冲动(“这就是她说的”)。

0

在这一行:

CGPoint impulse = ccpMult(mtd, i); 

MTD需要已经正常化。发生错误是因为在原始代码中,mtd是在上一行中标准化的,而不是在代码中。你可以做这样的事情解决它:

CGPoint impulse = ccpMult(ccpNormalize(mtd), i);