2016-05-31 10 views
3

Ich erstelle eine 2D-Physik-Engine, und ich habe Probleme mit einer bestimmten Art von Kollision zwischen beweglichen und unbeweglichen Objekten. Was ich mit "beweglich" meine, ist, dass sich die (x, y) -Werte ändern können, nicht dass sich der Referenzrahmen ändern kann oder nicht.Wie löst man eine 2D-Kollision mit einem unbeweglichen Objekt?

Zum Beispiel wäre ein Ball, der gegen eine Wand schlägt, etwas, das beweglich mit etwas Unbeweglichem kollidiert.

ball and wall collision

Ich glaube, dass ich so etwas wie Normalkraft in dieser Situation verwenden muß, aber ich bin nicht sicher, wie das für die Suche nach dem Ergebnis der Kollision verwendet werden würde.

Hier ist der Code, den ich bisher habe. Dieser Code ist für eine Kollision zwischen zwei beweglichen Einheiten, aber ich brauche einen Fall für hinzufügen, wenn man sich nicht bewegt:

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); 

    } 

Ich habe versucht, die Geschwindigkeit des unbeweglichen Gegenstand auf das Gegenteil des beweglichen Objekts Geschwindigkeit einstellen, aber das brachte die Dinge dazu, ineinander zu gehen.

+0

Ihr "unbewegliches" Objekt hat einen 'Velocity', die sich ändern können. Ist das etwas wie die Geschwindigkeit, mit der man sich bewegt? – Beta

+0

Ich glaube nicht. Sollte das unbewegliche Objekt nicht die gleiche Kraft in die entgegengesetzte Richtung ausüben? (Ich bin mir nicht ganz sicher, ob Ihre Frage zur Klarstellung war oder wenn Sie mich zur Antwort führen wollen) –

+0

* "Sollte nicht? * Sie haben zwei Entitäten,' a' und 'b'. Welche von ihnen ist unbeweglich, und warum stellst du seine Geschwindigkeit ein? – Beta

Antwort

0

Ich konnte Hilfe von einem Freund bekommen und wir haben diesen Algorithmus ausgearbeitet, damit Objekte während einer Kollision von unbeweglichen Objekten reflektiert werden.

Modified Original-Funktion:

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); 
      } 
     } 
    } 

Reflection Funktion:

 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; 
    } 
Verwandte Themen