Я создаю игру по исследованию космоса, и в настоящее время я начал работать над гравитацией (в C # с XNA).
Гравитация все еще нуждается в настройке, но прежде чем я смогу это сделать, мне нужно решить некоторые проблемы производительности с моими физическими вычислениями.
При этом используется 100 объектов, обычно при рендеринге 1000 из них без физических вычислений получается более 300 FPS (что является моим пределом FPS), но более 10 объектов приводят игру (и единственный поток, на котором она выполняется) к ее колени при выполнении физических расчетов.
Я проверил использование своего потока, и первый поток убивал себя от всей работы, поэтому я решил, что мне просто нужно сделать физический расчет в другом потоке. Однако, когда я пытаюсь запустить метод Update класса Gravity.cs в другом потоке, даже если в методе Gravity Update ничего нет, игра все равно проигрывает 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;
}
}
Да, знаю. Это вложенный цикл foreach, но я не знаю, как еще сделать расчет гравитации, и, похоже, это работает, он настолько интенсивен, что ему нужен собственный поток. (Даже если кто-то знает супер эффективный способ выполнения этих вычислений, я все равно хотел бы знать, как я МОЖЕТ сделать это на нескольких потоках)
EntityEngine.cs (управляет экземпляром 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 создается в Game1.cs, а его метод Update () вызывается в Game1.cs.
Мне нужно, чтобы мои физические расчеты в Gravity.cs запускались каждый раз, когда игра обновляется, в отдельном потоке, чтобы вычисления не замедляли игру до ужасно низкого (0-2) FPS.
Как мне сделать так, чтобы этот поток работал? (любые предложения по улучшению системы Planetary Gravity приветствуются, если у кого-то они есть)
Я также не ищу урок о том, почему я не должен использовать многопоточность или опасность неправильного использования, я ищу прямой ответ о том, как это сделать. Я уже час час гуглю этот самый вопрос с небольшими результатами, которые я понял или помог. Я не имею в виду грубость, но мне, как программисту, всегда трудно получить прямой осмысленный ответ, обычно я получаю ответ настолько сложный, что я легко смог бы решить свою проблему, если бы понял это, или кто-то говорит, почему я не должен делать то, что я хочу, и не предлагает никаких альтернатив (это полезно).
Спасибо вам за помощь!
РЕДАКТИРОВАТЬ : После прочтения ответов, которые я получил, я вижу, что вы, ребята, на самом деле все равно, и не просто пытаться высказать ответ, который может сработать. Я хотел убить двух зайцев одним ударом (улучшить производительность и изучить некоторые основы многопоточности), но, похоже, большая часть проблемы заключается в моих вычислениях, и что многопоточность доставляет больше хлопот, чем стоит увеличения производительности. Спасибо всем, я прочитаю ваши ответы еще раз и опробую ваши решения, когда я закончу со школой, еще раз спасибо!
k
этой O(n^2)
проблемы много.
sin² + cos² ≡ 1
он уже нормализован! Вы могли бы просто использовать исходный вектор, который соединяет два интересующих вас объекта, и нормализовать этот. Никаких звонков не нужно.