Ich baue ein Weltraum-Erkundungsspiel und arbeite gerade an der Schwerkraft (In C # mit XNA).
Die Schwerkraft muss noch optimiert werden, aber bevor ich das tun kann, muss ich einige Leistungsprobleme mit meinen physikalischen Berechnungen beheben.
Hierbei werden 100 Objekte verwendet. Normalerweise werden 1000 davon ohne physische Berechnungen mit mehr als 300 FPS (was meine Obergrenze für FPS ist) gerendert. Bei mehr als 10 Objekten wird jedoch das Spiel (und der einzelne Thread, auf dem es ausgeführt wird) auf die Obergrenze gebracht Knie beim Berechnen der Physik.
Ich habe meine Thread-Nutzung überprüft und der erste Thread hat sich von der ganzen Arbeit selbst erledigt, also dachte ich, ich müsste nur die Physikberechnung für einen anderen Thread durchführen. Wenn ich jedoch versuche, die Update-Methode der Gravity.cs-Klasse in einem anderen Thread auszuführen, ist das Spiel immer noch auf 2 FPS beschränkt, auch wenn die Update-Methode von Gravity nichts enthält.
Schwerkraft.cs
public void Update()
{
foreach (KeyValuePair<string, Entity> e in entityEngine.Entities)
{
Vector2 Force = new Vector2();
foreach (KeyValuePair<string, Entity> e2 in entityEngine.Entities)
{
if (e2.Key != e.Key)
{
float distance = Vector2.Distance(entityEngine.Entities[e.Key].Position, entityEngine.Entities[e2.Key].Position);
if (distance > (entityEngine.Entities[e.Key].Texture.Width / 2 + entityEngine.Entities[e2.Key].Texture.Width / 2))
{
double angle = Math.Atan2(entityEngine.Entities[e2.Key].Position.Y - entityEngine.Entities[e.Key].Position.Y, entityEngine.Entities[e2.Key].Position.X - entityEngine.Entities[e.Key].Position.X);
float mult = 0.1f *
(entityEngine.Entities[e.Key].Mass * entityEngine.Entities[e2.Key].Mass) / distance * distance;
Vector2 VecForce = new Vector2((float)Math.Cos(angle), (float)Math.Sin(angle));
VecForce.Normalize();
Force = Vector2.Add(Force, VecForce * mult);
}
}
}
entityEngine.Entities[e.Key].Position += Force;
}
}
Ja ich weiß. Es ist eine verschachtelte foreach-Schleife, aber ich weiß nicht, wie ich die Gravitationsberechnung ausführen soll, und das scheint zu funktionieren, es ist nur so intensiv, dass es einen eigenen Thread benötigt. (Auch wenn jemand eine super effiziente Methode kennt, um diese Berechnungen durchzuführen, möchte ich trotzdem wissen, wie ich es stattdessen auf mehreren Threads machen KÖNNTE.)
EntityEngine.cs (verwaltet eine Instanz von Gravity.cs)
public class EntityEngine
{
public Dictionary<string, Entity> Entities = new Dictionary<string, Entity>();
public Gravity gravity;
private Thread T;
public EntityEngine()
{
gravity = new Gravity(this);
}
public void Update()
{
foreach (KeyValuePair<string, Entity> e in Entities)
{
Entities[e.Key].Update();
}
T = new Thread(new ThreadStart(gravity.Update));
T.IsBackground = true;
T.Start();
}
}
EntityEngine wird in Game1.cs erstellt und die Update () -Methode in Game1.cs aufgerufen.
Ich benötige meine Physikberechnung in Gravity.cs, um jedes Mal, wenn das Spiel aktualisiert wird, in einem separaten Thread ausgeführt zu werden, damit die Berechnung das Spiel nicht auf schrecklich niedrige (0-2) FPS verlangsamt.
Wie würde ich vorgehen, damit dieses Einfädeln funktioniert? (Vorschläge für ein verbessertes Planetary Gravity-System sind willkommen, wenn jemand sie hat.)
Ich bin auch nicht auf der Suche nach einer Lektion, warum ich das Einfädeln nicht verwenden sollte oder die Gefahren einer falschen Verwendung. Ich suche nach einer klaren Antwort, wie das geht. Ich habe bereits eine Stunde damit verbracht, genau diese Frage mit kleinen Ergebnissen zu googeln, die ich verstand oder die hilfreich waren. Ich möchte nicht unhöflich abschneiden, aber es scheint für einen Programmierer immer schwierig zu sein, eine eindeutige und aussagekräftige Antwort zu erhalten. Normalerweise bekomme ich eine Antwort, die so komplex ist, dass ich mein Problem leicht lösen kann, wenn ich es verstehe, oder Jemand sagt, warum ich nicht tun sollte, was ich tun möchte, und bietet keine Alternativen an (die hilfreich sind).
Danke für die Hilfe!
EDIT : Nachdem ich die Antworten gelesen habe, sehe ich, dass es euch wirklich interessiert und ihr nicht nur versucht, eine Antwort herauszuspucken, die funktionieren könnte. Ich wollte zwei Fliegen mit einer Klappe schlagen (Verbesserung der Leistung und Erlernen einiger Grundlagen des Multlthreading), aber es scheint, dass das meiste Problem in meinen Berechnungen liegt und dass das Einfädeln mühsamer ist, als es sich für Leistungssteigerungen lohnt. Ich danke Ihnen allen, ich werde Ihre Antworten noch einmal durchlesen und Ihre Lösungen ausprobieren, wenn ich mit der Schule fertig bin. Nochmals vielen Dank!
k
dies das O(n^2)
Problem erheblich verringern .
sin² + cos² ≡ 1
ist er sowieso schon normalisiert! Sie hätten einfach den ursprünglichen Vektor verwenden können, der die beiden Objekte verbindet, an denen Sie interessiert sind, und diesen normalisiert. Es werden keinerlei Trigger-Anrufe benötigt.