2016-05-31 57 views
3

我正在創建一個2D物理引擎,並且遇到可移動和不可移動對象之間的某種類型的碰撞問題。我的意思是可移動的是(x,y)值可以改變,而不是參考框架可以或不可以改變。如何解決與不可移動物體的2D碰撞?

例如,一個碰到牆上的球會是可移動的與某些不動的東西碰撞的東西。

ball and wall collision

我相信,我需要使用類似普通部隊在這種情況下,但我不知道如何將用來查找碰撞的結果。

這是我到目前爲止的代碼。此代碼是兩個移動實體之間的碰撞,但我需要補充的情況下,當一個人不動了:

private static void UpdateEntities(PhysicsEntity a, PhysicsEntity b) 
    { 
     var collisionAngle = Math.Atan2(a.Position.Y - b.Position.Y, a.Position.X - b.Position.X); 
     var angleA = a.Velocity.Direction - collisionAngle; 
     var angleB = b.Velocity.Direction - collisionAngle; 

     var vAx = a.Velocity.Magnitude * Math.Cos(angleA); 
     var vAy = a.Velocity.Magnitude * Math.Sin(angleA); 
     var vBx = b.Velocity.Magnitude * Math.Cos(angleB); 
     var vBy = b.Velocity.Magnitude * Math.Sin(angleB); 

     var vfAx = ((vAx * (a.Mass - b.Mass) + 2 * b.Mass * vBx)/(a.Mass + b.Mass)) * a.Material.Elasticity; 
     var vfBx = ((vBx * (b.Mass - a.Mass) + 2 * a.Mass * vAx)/(a.Mass + b.Mass)) * b.Material.Elasticity; 
     var vfAy = vAy * a.Material.Elasticity; 
     var vfBy = vBy * b.Material.Elasticity; 

     var magA = Math.Sqrt(Math.Pow(vfAx, 2) + Math.Pow(vfAy, 2)); 
     var magB = Math.Sqrt(Math.Pow(vfBx, 2) + Math.Pow(vfBy, 2)); 
     var dirA = Math.Atan2(vfAy, vfAx) + collisionAngle; 
     var dirB = Math.Atan2(vfBy, vfBx) + collisionAngle; 

     a.Velocity.X = magA * Math.Cos(dirA); 
     a.Velocity.Y = magA * Math.Sin(dirA); 
     b.Velocity.X = magB * Math.Cos(dirB); 
     b.Velocity.Y = magB * Math.Sin(dirB); 

    } 

我試過的不可移動物體的速度設置爲可移動物體的速度相反,但導致事物相互進入。

+0

你的 「不動產」 的對象有一個'Velocity',這可以改變。這就像是涉及移動的速度嗎? – Beta

+0

我不這麼認爲。不動的物體不應該在相反的方向上施加相同的力量嗎? (我不完全確定你的問題是爲了澄清,還是如果你想引導我回答) –

+0

*「不應該?*你有兩個實體,'a'和'b'。哪一個是不動的,你爲什麼要設置它的速度? – Beta

回答

0

我能夠從朋友那裏得到幫助,並且我們計算出了這種算法,讓物體在碰撞過程中從不可移動物體反射回來。

修改後的原始功能:

private static void UpdateEntities(PhysicsEntity a, PhysicsEntity b) 
    { 
     var collisionAngle = Math.Atan2(a.Position.Y - b.Position.Y, a.Position.X - b.Position.X); 

     if (a.IsMoveable && b.IsMoveable) 
     { 
      var angleA = a.Velocity.Direction - collisionAngle; 
      var angleB = b.Velocity.Direction - collisionAngle; 

      var vAx = a.Velocity.Magnitude * Math.Cos(angleA); 
      var vAy = a.Velocity.Magnitude * Math.Sin(angleA); 
      var vBx = b.Velocity.Magnitude * Math.Cos(angleB); 
      var vBy = b.Velocity.Magnitude * Math.Sin(angleB); 

      var vfAx = ((vAx * (a.Mass - b.Mass) + 2 * b.Mass * vBx)/(a.Mass + b.Mass)) * a.Material.Elasticity; 
      var vfBx = ((vBx * (b.Mass - a.Mass) + 2 * a.Mass * vAx)/(a.Mass + b.Mass)) * b.Material.Elasticity; 
      var vfAy = vAy * a.Material.Elasticity; 
      var vfBy = vBy * b.Material.Elasticity; 

      var magA = Math.Sqrt(Math.Pow(vfAx, 2) + Math.Pow(vfAy, 2)); 
      var magB = Math.Sqrt(Math.Pow(vfBx, 2) + Math.Pow(vfBy, 2)); 
      var dirA = Math.Atan2(vfAy, vfAx) + collisionAngle; 
      var dirB = Math.Atan2(vfBy, vfBx) + collisionAngle; 

      a.Velocity.X = magA * Math.Cos(dirA); 
      a.Velocity.Y = magA * Math.Sin(dirA); 
      b.Velocity.X = magB * Math.Cos(dirB); 
      b.Velocity.Y = magB * Math.Sin(dirB); 
     } 
     else 
     { 
      var sign = Math.Sign(collisionAngle); 
      collisionAngle *= sign; 
      while (collisionAngle > Math.PI/2) 
      { 
       collisionAngle -= Math.PI/2; 
      } 
      collisionAngle *= sign; 
      if (a.IsMoveable) 
      { 
       Reflection(ref a, b, collisionAngle); 
      } 
      else 
      { 
       Reflection(ref b, a, collisionAngle); 
      } 
     } 
    } 

反射功能:

 private static void Reflection(ref PhysicsEntity movable, PhysicsEntity immovable, double collisionAngle) 
    { 
     if (Math.Abs(collisionAngle - Math.PI/2) < Universe.Epsilon) 
     { 
      // take the velocity vector, rotate it 180 degrees, scale it 
      movable.Velocity.X *= -1; 
      movable.Velocity.Y *= -1; 
     } 
     else if (Math.Abs(movable.Position.Y - immovable.Position.Y) < Universe.Epsilon || 
       (movable.Position.X > movable.CollisionPoint.X^movable.Position.Y < movable.CollisionPoint.Y)) 
     { 
      //take velocity vector, rotate CCW by 2*collisionAngle, scale it 
      var rotateAngle = 2 * collisionAngle; 
      var xPrime = movable.Velocity.X * Math.Cos(rotateAngle) - movable.Velocity.Y * Math.Sin(rotateAngle); 
      var yPrime = movable.Velocity.Y * Math.Cos(rotateAngle) - movable.Velocity.X * Math.Sin(rotateAngle); 
      movable.Velocity.X = xPrime; 
      movable.Velocity.Y = yPrime; 
     } 
     else 
     { 
      //take the vector, rotate it CCW by 360-2*collisionAngle, scale it 
      var rotateAngle = 2 * (Math.PI - collisionAngle); 
      var xPrime = movable.Velocity.X * Math.Cos(rotateAngle) - movable.Velocity.Y * Math.Sin(rotateAngle); 
      var yPrime = movable.Velocity.Y * Math.Cos(rotateAngle) - movable.Velocity.X * Math.Sin(rotateAngle); 
      movable.Velocity.X = xPrime; 
      movable.Velocity.Y = yPrime; 
     } 

     movable.Velocity.X *= movable.Material.Elasticity; 
     movable.Velocity.Y *= movable.Material.Elasticity; 
    }