2013-03-19 57 views
0

我有一個仿真,其中有多個圓形在2D空間中移動。2D彈性碰撞'Sticking'問題

它們之間有碰撞檢測,彈性碰撞在95%的時間內工作。然而,有時候,當兩個球碰到一起時,它們會彼此粘在一起並重疊,經常在相互粘合的同時繞着彼此運動。

我不確定如何解決這個問題。

我的衝突管理功能如下:

void manageCollision(Particle particleA, Particle particleB) 
{ 
    float distanceX = particleA.Position.X - particleB.Position.X; 
    float distanceY = particleA.Position.Y - particleB.Position.Y; 
    double collisionAngle = Math.Atan2(distanceY, distanceX); 
    double pA_magnitude = Math.Sqrt(particleA.Velocity.X * particleA.Velocity.X + particleA.Velocity.Y * particleA.Velocity.Y); 
    double pB_magnitude = Math.Sqrt(particleB.Velocity.X * particleB.Velocity.X + particleB.Velocity.Y * particleB.Velocity.Y); 
    double pA_direction = Math.Atan2(particleA.Velocity.Y, particleA.Velocity.X); 
    double pB_direction = Math.Atan2(particleB.Velocity.Y, particleB.Velocity.X); 
    double pA_newVelocityX = pA_magnitude * Math.Cos(pA_direction - collisionAngle); 
    double pA_newVelocityY = pA_magnitude * Math.Sin(pA_direction - collisionAngle); 
    double pB_newVelocityX = pB_magnitude * Math.Cos(pB_direction - collisionAngle); 
    double pB_newVelocityY = pB_magnitude * Math.Sin(pB_direction - collisionAngle); 
    double pA_finalVelocityX = ((particleA.Mass - particleB.Mass) * pA_newVelocityX + (particleB.Mass + particleB.Mass) * pB_newVelocityX)/(particleA.Mass + particleB.Mass); 
    double pB_finalVelocityX = ((particleA.Mass + particleA.Mass) * pA_newVelocityX + (particleB.Mass - particleA.Mass) * pB_newVelocityX)/(particleA.Mass + particleB.Mass); 
    double pA_finalVelocityY = pA_newVelocityY; 
    double pB_finalVelocityY = pB_newVelocityY; 
    particleA.Velocity = new Vector2((float)(Math.Cos(collisionAngle) * pA_finalVelocityX + Math.Cos(collisionAngle + Math.PI/2) * pA_finalVelocityY), (float)(Math.Sin(collisionAngle) * pA_finalVelocityX + Math.Sin(collisionAngle + Math.PI/2) * pA_finalVelocityY)); 
    particleB.Velocity = new Vector2((float)(Math.Cos(collisionAngle) * pB_finalVelocityX + Math.Cos(collisionAngle + Math.PI/2) * pB_finalVelocityY), (float)(Math.Sin(collisionAngle) * pB_finalVelocityX + Math.Sin(collisionAngle + Math.PI/2) * pB_finalVelocityY)); 
} 

每個球或顆粒用隨機的質量和半徑滋生。

該函數的方法的更新類型中調用,例如:

Particle pA = particles[i]; 
for (int k = i + 1; k < particles.Count(); k++) 
{ 
    Particle pB = particles[k]; 
    Vector2 delta = pA.Position - pB.Position; 
    float dist = delta.Length(); 

    if (dist < particles[i].Radius + particles[k].Radius && !particles[i].Colliding && !particles[k].Colliding) 
    { 
     particles[i].Colliding = true; 
     particles[k].Colliding = true; 
     manageCollision(particles[i], particles[k]); 
     particles[i].initColorTable(); // Upon collision, change the color 
     particles[k].initColorTable(); 
     totalCollisions++; 
    } 
    else 
    { 
     particles[i].Colliding = false; 
     particles[k].Colliding = false; 
    } 
} 

回答

1

這種情況從離散計算和持續時間的大的步長莖。

當你用某個時間間隔dt觀察物體時,可以觀察兩個圓之間的某個交點並調用你的碰撞方法,但是在下一個時間步中它們可能仍然重疊,儘管碰撞後它們在不同方向上前一步。

爲了減少這種影響,您可以嘗試較小的時間步長,以便可以減少物體之間的重疊率。 作爲一個更復雜的解決方案,您可以爲每個步驟保留一個碰撞對象列表,並且在迭代過程中,如果當前相交的圓圈在上一步中有任何「事件」,則可以檢查此列表。