2016-06-20 4 views
0

Ich versuche, eine 2D-Spiel-Engine zu machen, aber ich kann nicht scheinen, Kollisionen zu bekommen, um die ganze Zeit zu arbeiten (Oftmals bleiben Dinge stecken oder passieren sich gegenseitig). Ohne zu sehr in den Code einzusteigen, hier ist die Reihenfolge, in der ich aktualisiere.Was ist die richtige Reihenfolge der Operationen für Kollisionserkennung und Reaktion?

  1. Benutzereingabe abrufen und aktualisieren die Spieler Geschwindigkeit
  2. Speichern Sie die Position für jede Entität, bewegen dann die Geschwindigkeit/Aktualisierungsintervall Einheiten
  3. überprüfen jede bewegliche Einheit für Kollisionen gegenüber allen anderen Einheiten. Wenn das Objekt mit einem Objekt kollidiert, wird es an seine alte Position verschoben, und die neuen Geschwindigkeiten werden für beide kollidierenden Objekte festgelegt.

Der Kollisionsimpuls wird in dieser Funktion berechnet:

private static void CollisionImpulse(PhysicsEntity a, PhysicsEntity b) 
    { 
     var relative = b.Velocity.Vector - a.Velocity.Vector; 
     var normal = Vector2.Normalize(relative); 
     var e = Math.Min(a.Material.Elasticity, b.Material.Elasticity); 
     var j = (-(1 + e) * Vector2.Dot(relative, normal))/
       (Vector2.Dot(normal, normal) * (a.InverseMass + b.InverseMass)); 
     if (double.IsNaN(j)) return; 

     var velocityA = normal * (float) (j/a.Mass); 
     var velocityB = normal * (float) (j/b.Mass); 

     a.Velocity.X -= velocityA.X; 
     a.Velocity.Y -= velocityA.Y; 

     if (!b.Movable) return; 
     b.Velocity.X += velocityB.X; 
     b.Velocity.Y += velocityB.Y; 
     b.Position = b.OldPosition; 
    } 

und dies ist die Funktion für die Kollisionen zu überprüfen:

public override void Update() 
     { 
      foreach (var entity in Universe.PhysicsEntities) 
      { 
       if (entity.Equals(this) || entity.Collided) continue; 
       CollisionResolution.ResolveCollision(this, entity); 
       if (!Collided) continue; 
       Position = OldPosition; 
       break; 
      } 
     } 

Ich habe ein um den Code zu optimieren versucht, einige Tage, aber ich kann nicht herausfinden, was falsch ist. Ich hatte gehofft, dass ein paar frische Augen ein wenig Licht in mein Dilemma bringen könnten.

+0

Was ist der unerwünschte Effekt, den Sie beobachten? – heltonbiker

+0

Es gab viele, als ich den Code geändert habe. Die erste ist, wenn A neben B steht und sie sich kaum berühren, und A sich nach links bewegt, B über A hinweg. Manchmal bleiben A und B aneinander haften. –

Antwort

1

Es gibt ein grundlegendes Problem mit Schritt 3 "Wenn das Objekt mit etwas kollidiert, wird es an seine alte Position verschoben ..." - Da Sie dieses Objekt jetzt erneut bewegen, müssen Sie die Kollisionserkennung erneut ausführen für alle vorherigen Entitäten gegen diese Entität, sonst könnten Sie eine Überlappung verursachen.

z. Wenn Sie 3 Poolbälle (A, B, C) haben, bewegen Sie alle 3 zu ihren gewünschten neuen Positionen zu A ', B', C '(in Ihrem Schritt 2). Jetzt für Schritt 3 überprüfen Sie und A'B 'und A'C' kollidieren nicht, und sie nicht, aber dann überprüfen Sie B'C 'und sie kollidieren, also in Ihrer Lösung bewegen Sie B', C 'zurück zu B, C - aber jetzt technisch können Sie bewegt B und/oder C haben, so dass es jetzt mit A. sich schneid ist

um Ihren Schritt 3 Arbeit machen müssen Sie entweder:

1) stellen Sie sicher, dass kein Objekte überlappen sich beim Start, und wenn Sie in Schritt 3 eine Kollision feststellen, führen Sie entweder (a) die Kollision für jedes vorherige Objekt erneut aus, das zuvor nicht mit diesen Objekten kollidiert ist, ODER führen Sie den gesamten Schritt erneut aus 3 bis keine Objekte in der letzten Schleife zurückgesetzt wurden. Dies kann teuer werden, wenn Sie viele Objekte haben und sich alle gegenseitig zurücksetzen.

oder:

2) Anstelle Objekte zu ihren letzten Frame der „sicheren“ Position jedes Mal zurückzusetzen, die resultierende Kraft (so Beschleunigung, nicht Geschwindigkeit) wird im Zusammenhang mit wie viel die Objekte dringen. Dies ist in 3D-Physik-Engines üblich und kann dazu führen, dass Objekte explodieren, wenn sie sich zu sehr durchdringen.

Beachten Sie auch, dass wenn Sie ein Objekt sehr weit in 1 Rahmen bewegen (z. B. mehr als die Hälfte), könnte es möglicherweise durch ein anderes Objekt ohne Kollisionsüberlappungserkennung feuern. Dies wird oft als "Kugel-durch-Papier-Problem" bezeichnet.

+0

Ich kam vor einer Woche oder zwei zu demselben Schluss.Schritt 3 wurde benötigt, um die Entitäten rekursiv zurück zu bewegen, wenn sie kollidiert waren, aber die Art und Weise, wie Sie es erklären, macht auch sehr viel Sinn. –

Verwandte Themen