Нужна помощь в определении орбит в 2D для моей игры - PullRequest
0 голосов
/ 02 февраля 2019

В игре, которую я создаю, идея состоит в том, что курсор мыши представляет центр масс, и вокруг него вращаются объекты.Сам курсор не является объектом, и между курсором и объектами нет столкновения.

Идеальным методом будет тот, в котором я могу ввести x и y координаты цели и, возможно, радиус орбиты, и объект выйдет на орбитуи будет ускоряться постоянно.
Когда я перемещаю мышь, объект будет следовать;и когда я остановлю его, он упадет на тот же радиус орбиты.
Ускорение объектов также должно меняться, так что это дает эффект, что мышь имеет большую или меньшую массу.

Я думал, что лучший способ достичь этого, вероятно, будет с векторами.

В классе «Снаряд» я дал каждому полету по 4 поля: координата x, координата y, скорость PVector и соотношения PVector (ускорение).

Первое, что я попробовал, это дать объекту постоянное ускорение.Вектор скорости начинается с нуля, вектор ускорения вычисляется, его величина затем устанавливается на некоторое значение и добавляется к вектору скорости.Это создавало очень большие орбиты, медленное ускорение, и когда мышь перемещалась, орбита становилась больше.

Далее я попытался увеличить ускорение, когда оно ближе к центру масс, вдохновленному реальными планетами.Это тоже не сработало.Орбиты были все еще слишком большими и неуправляемыми.Вроде разочарован, я пытался сделать ускорение постоянно увеличивающимся, что дало лучшие результаты.Теперь орбита становится меньше, но она продолжает уменьшаться до некоторого радиуса и затем останавливается.Это было бы идеально, если бы радиус, при котором он прекращал уменьшаться, был бы настраиваемым, но независимо от параметров, орбита всегда слишком велика, а размер орбиты постоянно уменьшался до безумия.Я предполагаю, что ускорение и скорость каким-то образом оказываются в равновесии, а затем орбита перестает уменьшаться.

void move(float x,float y,float accm)
  {
    PVector target = new PVector(x, y);
    PVector ball = new PVector(this.x, this.y);
    acc = PVector.sub(target, ball);
    acc.setMag(accm);
    speed.add(acc);
    println(acc.mag() + " " + speed.mag());
    this.x = this.x + speed.x;
    this.y = this.y + speed.y;
  }

Эта функция дала наилучшие результаты.Функция вызывается в draw():

if(mousePressed == true)
  {
    for(i=0;i<nproj;i++)
    {
      a[i].move(mouseX, mouseY,k);
    }
    k += n;
  }

k - число, данное функции, а n - скорость, с которой ускорение увеличивается.Я пробовал много разных величин ускорения и разных скоростей ускорения и просто не мог понять это.Nproj - количество снарядов, a - название массива снарядов.

Я обнаружил, что для k = 0 и n = 0,002 он дает наиболее надежные и стабильные результаты.Если n больше (около 0,01 или больше), объекты иногда случайным образом отлетают намного дальше, чем ожидалось, и это фактически увеличивает радиус орбиты.По мере увеличения ускорения это происходит чаще, и объект иногда оказывается за пределами экрана, а затем никогда не возвращается.Я знаю, что радиус орбиты не существует, потому что орбиты эллиптические, но это просто облегчает объяснение.

Обновление: это то, что я до сих пор придумал

void move(float x,float y,float accm)
  {
    PVector target = new PVector(x, y);
    PVector ball = new PVector(this.x, this.y);
    acc = PVector.sub(target, ball);
    acc.setMag(accm);
    vel.add(acc);
    this.x = this.x + vel.x;
    this.y = this.y + vel.y;
    vel.limit(15);
  }

и в draw()

if(mousePressed == true)
  {
    for(i=0;i<nproj;i++)
    {
      a[i].move(mouseX, mouseY,k);
    }
    k += n;
    if(k > 25)
    n = 0;
  }

Ограничивая вектор скорости и постоянно увеличивая вектор ускорения, разность величин начинает увеличиваться, и поскольку вектор ускорения увеличивается, а вектор скорости постоянен, а вектор ускорения направлен к целисумма векторов начинает медленно указывать все больше и больше на цель.Условие if(k < 25) ограничивает ускорение, и, изменяя предел ускорения, вы можете изменить радиус орбиты.

1 Ответ

0 голосов
/ 06 февраля 2019

Я думаю, что вы, вероятно, получили бы более быстрый ответ на https://physics.stackexchange.com/ и сформулировали бы свой вопрос как "как мне моделировать гравитацию в игре?"

В любом случае, я попробую...

В классе «Снаряд» я дал каждому полету 4 поля: координата x, координата y, скорость PVector и PVector соотв.

Пока что звучит хорошо, кроме вас.Не нужно хранить вектор ускорения с объектом.Вы будете вычислять новый вектор ускорения для каждого объекта на каждом «тике» вашего моделирования.

Я бы использовал стандартную физическую терминологию здесь и назвал бы вектор каждого объекта velocity вместо speed.

Далее я попытался увеличить ускорение, когда оно ближе к центру масс, вдохновленному фактическими планетами.

Такое поведение должно происходить естественным образом, если вы используете правильный алгоритм длявычисление орбиты.

Ваше "солнце" и "планеты" имеют массу.Массы притягивают друг друга с помощью гравитационной силы, которая составляет F = G * m1 * m2 / d^2 из Википедии .

Помните, что Force = mass * acceleration, и вы получите ускорение как a = m * G / d^2, где m - этомасса другого объекта (в данном случае солнца), а d - расстояние между двумя объектами.Таким образом, важная часть заключается в том, что ускорение объекта под действием силы тяжести изменяется в зависимости от квадрата расстояния между двумя объектами.

Таким образом, ваш основной алгоритм для одного тика симуляции выглядит следующим образом:

  • Для каждой планеты рассчитать вектор ускорения
  • Использовать расстояние до «солнца» в квадрате в качестве величины вектора ускорения (умноженное на постоянную)значение, которое зависит от вашей "гравитационной постоянной" и массы вашего Солнца), и, конечно, это направление от планеты к Солнцу
  • Добавьте этот вектор ускорения к вектору скорости для планеты
  • Добавьте вектор скорости в положение (x, y) планеты, чтобы переместить ее вперед.

С соответствующими значениями длины каждого такта моделирования, гравитационной постоянной и массы Солнца.это должно выглядеть довольно разумно.

Поскольку вы предполагаете, что все планеты независимы иЕсли вы не можете столкнуться, вы можете просто выполнить вычисления независимо для каждой планеты.

Однако, я думаю, что игра может быть более интересной с более точной симуляцией.В действительности каждый объект имеет гравитационную силу на каждом другом объекте.Это означало бы зацикливание на всех парах объектов и выполнение одного и того же вида расчета ускорения / скорости / положения.

Смысл игры мог бы заключаться в том, чтобы «планеты» перемещались с одной стороны экрана кдругие, во все более сложных стартовых конфигурациях, поскольку все они влияют друг на друга и движутся в разных направлениях.

Для того, чтобы все это работало хорошо, было бы важно установить массу "солнца" во многихраз больше, чем масса планет, и выбрать разумное значение для вашей гравитационной постоянной в зависимости от времени вашего моделирования.Вам придется поиграть с этими константами, чтобы найти наилучшие результаты.

...