Estou construindo um jogo de exploração espacial e atualmente comecei a trabalhar com gravidade (em C # com XNA).
A gravidade ainda precisa ser aprimorada, mas antes que eu possa fazer isso, preciso resolver alguns problemas de desempenho com meus cálculos de física.
Isso está usando 100 objetos, normalmente renderizando 1000 deles sem cálculos de física chega a mais de 300 FPS (que é meu limite de FPS), mas mais de 10 objetos traz o jogo (e o único segmento em que ele é executado) joelhos ao fazer cálculos de física.
Eu verifiquei o uso do meu thread e o primeiro thread estava acabando com todo o trabalho, então achei que só precisava fazer o cálculo da física em outro thread. No entanto, quando tento executar o método Update da classe Gravity.cs em outro segmento, mesmo que o método Update da Gravity não contenha nada, o jogo ainda diminui para 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;
}
}
Sim, eu sei. É um loop foreach aninhado, mas não sei mais como fazer o cálculo da gravidade, e isso parece funcionar, é tão intenso que ele precisa de seu próprio encadeamento. (Mesmo que alguém conheça uma maneira super eficiente de fazer esses cálculos, eu ainda gostaria de saber como eu poderia fazê-lo em vários threads)
EntityEngine.cs (gerencia uma instância de 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 é criado no Game1.cs e seu método Update () é chamado no Game1.cs.
Preciso que meu cálculo físico no Gravity.cs seja executado sempre que o jogo for atualizado, em um thread separado, para que o cálculo não diminua o jogo para um FPS horrivelmente baixo (0-2).
Como eu faria para fazer esse rosqueamento funcionar? (quaisquer sugestões para um sistema de gravidade planetária aprimorado são bem-vindas, se alguém as tiver)
Também não estou procurando uma lição sobre por que não devo usar o encadeamento ou os perigos de usá-lo incorretamente. Estou procurando uma resposta direta sobre como fazê-lo. Eu já passei uma hora pesquisando essa questão com poucos resultados que entendi ou que foram úteis. Não quero parecer grosseiro, mas sempre parece difícil para um noob de programação obter uma resposta direta significativa. Geralmente, prefiro uma resposta tão complexa que seria capaz de resolver meu problema com facilidade, se eu entendesse isso, ou alguém dizendo por que não devo fazer o que quero e não oferecendo alternativas (que são úteis).
Obrigado pela ajuda!
Edição : Depois de ler as respostas que recebi, vejo que vocês realmente se importam e não estão apenas tentando dizer uma resposta que possa funcionar. Eu queria matar dois coelhos com uma cajadada (melhorando o desempenho e aprendendo algumas noções básicas de multithread), mas parece que a maior parte do problema está nos meus cálculos e que o threading é mais problemático do que vale a pena aumentar o desempenho. Obrigado a todos, vou ler suas respostas novamente e experimentar suas soluções quando terminar a escola, obrigado novamente!
k
deste O(n^2)
problema muito.
sin² + cos² ≡ 1
ele já está normalizado de qualquer maneira! Você poderia ter usado o vetor original que conecta os dois objetos nos quais está interessado e normalizado este. Não são necessárias chamadas trigonométricas.