2010-01-15 41 views
2

我想找個當靜態和運動中的球之間碰撞的發生,但我想出了算法,有時沒有檢測到碰撞和運動球穿過靜態的。移動的球體受重力影響,靜止的球體不受重力影響。簡單的2D碰撞問題

這裏是我的碰撞檢測代碼:

GLfloat whenSpheresCollide(const sphere2d &firstSphere, const sphere2d &secondSphere) 
{ 
    Vector2f relativePosition = subtractVectors(firstSphere.vPosition, secondSphere.vPosition); 
    Vector2f relativeVelocity = subtractVectors(firstSphere.vVelocity, secondSphere.vVelocity); 

    GLfloat radiusSum = firstSphere.radius + secondSphere.radius; 

    //We'll find the time when objects collide if a collision takes place 

    //r(t) = P[0] + t * V[0] 
    // 
    //d^2(t) = P[0]^2 + 2 * t * P[0] * V[0] + t^2 * V[0]^2 
    // 
    //d^2(t) = V[0]^2 * t^2 + 2t(P[0] . V[0]) + P[0]^2 
    // 
    //d(t) = R 
    // 
    //d(t)^2 = R^2 
    // 
    //V[0]^2 * t^2 + 2t(P[0] . V[0]) + P[0]^2 - R^2 = 0 
    // 
    //delta = (P[0] . V[0])^2 - V[0]^2 * (P[0]^2 - R^2) 
    // 
    // We are interested in the lowest t: 
    // 
    //t = (-(P[0] . V[0]) - sqrt(delta))/V[0]^2 
    // 

    GLfloat equationDelta = squaref(dotProduct(relativePosition, relativeVelocity)) - squarev(relativeVelocity) * (squarev(relativePosition) - squaref(radiusSum) ); 

    if (equationDelta >= 0.0f) 
    { 
     GLfloat collisionTime = (- dotProduct(relativePosition, relativeVelocity) - sqrtf(equationDelta))/squarev(relativeVelocity); 

     if (collisionTime >= 0.0f && collisionTime <= 1.0f/GAME_FPS) 
     { 
      return collisionTime; 
     } 
    } 

    return -1.0f; 
} 

這裏是調用碰撞檢測更新功能:

void GamePhysicsManager::updateBallPhysics() 
{ 
    // 
    //Update velocity 
    vVelocity->y -= constG/GAME_FPS; //v = a * t = g * 1 sec/(updates per second) 

    shouldApplyForcesToBall = TRUE; 

    vPosition->x += vVelocity->x/GAME_FPS; 
    vPosition->y += vVelocity->y/GAME_FPS; 

    if (distanceBetweenVectors(*pBall->getPositionVector(), *pBasket->getPositionVector()) <= pBasket->getRadius() + vectorLength(*vVelocity)/GAME_FPS) 
    { 
     //Ball sphere 
     sphere2d ballSphere; 
     ballSphere.radius = pBall->getRadius(); 
     ballSphere.mass = 1.0f; 
     ballSphere.vPosition = *(pBall->getPositionVector()); 
     ballSphere.vVelocity = *(pBall->getVelocityVector()); 


     sphere2d ringSphereRight; 
     ringSphereRight.radius = 0.05f; 
     ringSphereRight.mass = -1.0f; 
     ringSphereRight.vPosition = *(pBasket->getPositionVector()); 
     //ringSphereRight.vPosition.x += pBasket->getRadius(); 
     ringSphereRight.vPosition.x += (pBasket->getRadius() - ringSphereRight.radius); 
     ringSphereRight.vVelocity = zeroVector(); 


     GLfloat collisionTime = whenSpheresCollide(ballSphere, ringSphereRight); 

     if (collisionTime >= 0.0f) 
     { 
      DebugLog("collision"); 
      respondToCollision(&ballSphere, &ringSphereRight, collisionTime, pBall->getRestitution() * 0.75f); 
     } 

     // 
     //Implement selection of the results that are first to collide collision 

     vVelocity->x = ballSphere.vVelocity.x; 
     vVelocity->y = ballSphere.vVelocity.y; 

     vPosition->x = ballSphere.vPosition.x; 
     vPosition->y = ballSphere.vPosition.y; 
    } 

爲什麼沒有病例的100%被檢測碰撞?僅在70%的情況下才被發現。 謝謝。

UPDATE:問題似乎解決了,當我改變從30 FPS至10如何FPS影響我的碰撞檢測?

+1

那麼在這種情況下嘗試設置FPS很高和調試程序行由行,仔細觀察變量值如何與你認爲他們應該是一致的。 – 2010-01-15 19:14:10

+0

您能否提供有關respondToCollision功能的更多詳細信息?特別是,檢測與第三方的進一步衝突是否有效?你如何處理一個框架中的多個碰撞? – markets 2010-01-15 19:18:15

回答

1
delta = (P[0] . V[0])^2 - V[0]^2 * (P[0]^2 - R^2) 

不應認爲是增量= b - 交流?


[編輯]哦,我明白了,你的因素4,滿分。在那種情況下,你確定你正在考慮兩種解決方案嗎?

t = (-(P[0] . V[0]) - sqrt(delta))/V[0]^2 

t = (-(P[0] . V[0]) + sqrt(delta))/V[0]^2 
+0

我正在使用x之前的係數爲偶數時可以使用的替代公式。 – 2010-01-15 18:44:40

+0

我正在考慮只有一個解決方案 - 時間較短。我不感興趣,在更大的時間,因爲它會當物體之間的距離將是0,第二次(本身發生了較小的時間衝突)發生。 – 2010-01-15 19:01:29

+0

這可能是由於四捨五入錯誤 - 程序期望碰撞發生在下一幀,但由於輕微的舍入錯誤,在下一幀碰撞應該已經發生。嘗試用'雙打'替換你的'浮動',或者碰撞發生在幾幀之前(用'collisionTime <= 1.9f/GAME_FPS'代替'collisionTime <= 1.0f/GAME_FPS') – 2010-01-15 19:21:49

1

球的速度有多快被他們感動多大了?可以在一幀期間的球「跳」過第二個(即,是它的速度矢量長於它的寬度?)。

順着這些線索,如果您刪除上限這裏發生了什麼:

if (collisionTime >= 0.0f && collisionTime <= 1.0f/GAME_FPS) 
{ 
    return collisionTime; 
} 

如果球得太快,也許你的算法檢測到發生了不止一個幀前的碰撞。( ?)

+0

球體大小大致相同。 通常,此上限限定,如果碰撞會在下一幀期間發生。如果是,則報告碰撞。 – 2010-01-15 18:01:25