Buduję grę w eksplorację kosmosu i obecnie rozpocząłem pracę nad grawitacją (w C # z XNA).
Grawitacja wciąż wymaga ulepszenia, ale zanim to zrobię, muszę rozwiązać niektóre problemy z wydajnością w moich obliczeniach fizycznych.
Wykorzystuje 100 obiektów, zwykle renderując 1000 z nich bez obliczeń fizycznych, osiąga znacznie ponad 300 FPS (co jest moim ograniczeniem FPS), ale każde więcej niż 10 obiektów sprowadza grę (i pojedynczy wątek, na którym działa) do jej kolana podczas obliczeń fizycznych.
Sprawdziłem użycie wątku i pierwszy wątek zabijał się po całej pracy, więc pomyślałem, że po prostu muszę wykonać obliczenia fizyki dla innego wątku. Jednak gdy próbuję uruchomić metodę aktualizacji klasy Gravity.cs w innym wątku, nawet jeśli metoda aktualizacji Gravity nie ma w tym nic, gra wciąż spada do 2 FPS.
Gravity.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;
}
}
Tak, wiem. To zagnieżdżona pętla foreach, ale nie wiem, jak inaczej wykonać obliczenia grawitacyjne, i wydaje się, że to działa, jest tak intensywne, że potrzebuje własnego wątku. (Nawet jeśli ktoś zna super wydajny sposób wykonywania tych obliczeń, nadal chciałbym wiedzieć, jak MOGĘ to zrobić na wielu wątkach)
EntityEngine.cs (zarządza instancją 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 jest tworzony w Game1.cs, a jego metoda Update () jest wywoływana w Game1.cs.
Potrzebuję moich obliczeń fizycznych w Gravity.cs, aby były uruchamiane przy każdej aktualizacji gry, w osobnym wątku, aby obliczenia nie spowalniały gry do strasznie niskich (0-2) FPS.
W jaki sposób mógłbym sprawić, by wątkowanie działało? (wszelkie sugestie dotyczące ulepszonego systemu planetarnej grawitacji są mile widziane, jeśli ktoś je ma)
Nie szukam też lekcji, dlaczego nie powinienem używać wątków ani niebezpieczeństw związanych z niewłaściwym użyciem, szukam prostej odpowiedzi, jak to zrobić. Spędziłem już godzinę na wyszukiwaniu tego pytania z niewielkimi wynikami, które zrozumiałem lub były pomocne. Nie chcę odejść od niegrzeczności, ale zawsze wydaje się trudne jako programista, aby uzyskać prostą, sensowną odpowiedź, zwykle raczej otrzymuję odpowiedź tak złożoną, że z łatwością byłbym w stanie rozwiązać mój problem, jeśli go zrozumiałem, lub ktoś mówi, dlaczego nie powinienem robić tego, co chcę, i nie oferuje żadnych alternatyw (które są pomocne).
Dziękuję za pomoc!
EDYCJA : Po przeczytaniu odpowiedzi, które otrzymałem, widzę, że was obchodzi, a nie tylko próbujecie wyrzucić odpowiedź, która może zadziałać. Chciałem zabić dwa ptaki jednym kamieniem (poprawa wydajności i nauczenie się podstaw wielowątkowości), ale wydaje się, że większość problemu leży w moich obliczeniach, a gwintowanie jest bardziej kłopotliwe niż warte zwiększenia wydajności. Dziękuję wszystkim, jeszcze raz przeczytam wasze odpowiedzi i wypróbuję wasze rozwiązania, kiedy skończę szkołę, jeszcze raz dziękuję!
k
ten O(n^2)
problem.
sin² + cos² ≡ 1
tak jest już znormalizowany! Mogłeś po prostu użyć oryginalnego wektora, który łączy dwa interesujące Cię obiekty, i znormalizować ten. Żadne wywołania trig nie są potrzebne.