2009-05-21 126 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);