Программирование гладкого изменения тяги от текущего вектора скорости до целевого вектора

Im, не уверенный, почему но если я изменяю каскадный тип для УДАЛЕНИЯ его работы хорошо....

@OneToMany(mappedBy = "fileDetailId.conversation",cascade = CascadeType.REMOVE)

private Set<FileDetailDao> fileDetailDaoSet = new HashSet<>();
7
задан user128526 2 September 2009 в 01:05
поделиться

7 ответов

Все возвращается к уравнениям Ньютона:

F = m * a
s = s_o + v * t + a * t^2 / 2
v = v_o + a * t

В этом случае F - сила (тяга), a - ускорение, и м - масса корабля. s - текущее местоположение, s_o - исходное местоположение, v - скорость, а t - текущее время.

] Конечно, это прямая линия, поэтому, если вы хотите преобразовать в двух или трех измерениях, вам придется проделать некоторую математику. F , s , v и a - все векторы, что означает, что их направление одинаково важно. Технически t также является вектором, но поскольку время обычно идет только в одном направлении, нам не нужно об этом беспокоиться.

2d:
F^2 = F_x^2 + F_y^2 (use Pythagorean theorem to split force into components)
F_x = m * a_x
F_y = m * a_y
s_x = s_o_x + v_x * t + a_x * t^2 / 2
s_y = s_o_y + v_y * t + a_y * t^2 / 2
v_x = v_o_x + a_x * t
v_y = v_o_y + a_y * t

3d:
F^2 = F_x^2 + F_y^2 + F_z^2 (surprisingly, this works)
F_x = m * a_x
F_y = m * a_y
F_z = m * a_z
s_x = s_o_x + v_x * t + a_x * t^2 / 2
s_y = s_o_y + v_y * t + a_y * t^2 / 2
s_z = s_o_z + v_z * t + a_z * t^2 / 2
v_x = v_o_x + a_x * t
v_y = v_o_y + a_y * t
v_z = v_o_z + a_z * t

Теперь, чтобы отрегулировать вашу скорость в зависимости от направления игрока, у вас есть фиксированная общая сила ( F ), чтобы изменить вашу текущую скорость по направлению к игроку. В физике вещи не происходят мгновенно, но ваша цель должна состоять в том, чтобы минимизировать время, за которое происходит изменение ('t').

Это дает вам уравнение в терминах вашего текущего местоположения ( (s_o_x, s_o_y) или (s_o_x, s_o_y, s_o_z) ) и текущее местоположение вашего оппонента или ваше целевое местоположение ( (s_x, s_y) или (s_x, s_y, s_z) ) для вашей целевой скорости (не учитывает ускорение).

v_x = (s_x - s_o_x) / t
v_y = (s_y - s_o_y) / t

v_x = (s_x - s_o_x) / t
v_y = (s_y - s_o_y) / t
v_z = (s_z - z_o_y) / t

Мы можем заменить это на наше другое уравнение:

(s_x - s_o_x) / t = v_o_x + a_x * t
(s_y - s_o_y) / t = v_o_y + a_y * t

(s_x - s_o_x) / t = v_o_x + a_x * t
(s_y - s_o_y) / t = v_o_y + a_y * t
(s_z - z_o_y) / t = v_o_z + a_z * t

Затем мы решаем ускорение (это связано с силой, которой мы являемся пытается вычислить).

(s_x - s_o_x) / t^2 - v_o_x / t = a_x
(s_y - s_o_y) / t^2 - v_o_y / t = a_y

(s_x - s_o_x) / t^2 - v_o_x / t = a_x
(s_y - s_o_y) / t^2 - v_o_y / t = a_y
(s_z - z_o_y) / t^2 - v_o_z / t = a_z

Подставьте это в уравнение силы:

F_x = m * (s_x - s_o_x) / t^2 - m * v_o_x / t
F_y = m * (s_y - s_o_y) / t^2 - m * v_o_y / t

F_x = m * (s_x - s_o_x) / t^2 - m * v_o_x / t
F_y = m * (s_y - s_o_y) / t^2 - m * v_o_y / t
F_z = m * (s_z - z_o_y) / t^2 - m * v_o_z / t

Теперь решите для t :

t = (-m * v_o_x +/- sqrt(m^2 * v_o_x^2 - 4 * F_x * m * (s_x - s_o_x))) / 2 / F_x
t = (-m * v_o_y +/- sqrt(m^2 * v_o_y^2 - 4 * F_y * m * (s_y - s_o_y))) / 2 / F_y

t = (-m * v_o_x +/- sqrt(m^2 * v_o_x^2 - 4 * F_x * m * (s_x - s_o_x))) / 2 / F_x
t = (-m * v_o_y +/- sqrt(m^2 * v_o_y^2 - 4 * F_y * m * (s_y - s_o_y))) / 2 / F_y
t = (-m * v_o_z +/- sqrt(m^2 * v_o_z^2 - 4 * F_z * m * (s_z - s_o_z))) / 2 / F_z

Время должно сходиться, поэтому времена будут одинаковыми! Это дает нам систему уравнений для каждой координаты (плоскости и сферы). Обратите внимание, что существует несколько возможных значений, но некоторые из них связаны с мнимыми числами, поэтому вам придется исключить эти решения:

(-m * v_o_x +/- sqrt(m^2 * v_o_x^2 - 4 * F_x * m * (s_x - s_o_x))) / 2 / F_x
= (-m * v_o_y +/- sqrt(m^2 * v_o_y^2 - 4 * F_y * m * (s_y - s_o_y))) / 2 / F_y
F^2 = F_x^2 + F_y^2

(-m * v_o_x +/- sqrt(m^2 * v_o_x^2 - 4 * F_x * m * (s_x - s_o_x))) / 2 / F_x
= (-m * v_o_y +/- sqrt(m^2 * v_o_y^2 - 4 * F_y * m * (s_y - s_o_y))) / 2 / F_y
= (-m * v_o_z +/- sqrt(m^2 * v_o_z^2 - 4 * F_z * m * (s_z - s_o_z))) / 2 / F_z
F^2 = F_x^2 + F_y^2 + F_z^2

Решите для (F_x, F_y) или (F_x, F_y, F_z ) координирует, и у вас есть необходимая сила.

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

2
ответ дан 7 December 2019 в 01:24
поделиться

Вы должны мыслить в терминах правильной физики. У вас есть скорость, и вы хотите добавить ускорение. Вот и все, что нужно сделать - ускорение - это постепенное изменение скорости, которое будет притягивать противника к игроку, позволять ему пролететь мимо, замедлить (или повернуть), а затем вернуться к игроку.

Ускорение измеряется как d (скорость) / время. Вы хотите ускоряться по направлению к игроку в любой момент времени, поэтому каждый интервал (секунда, сотая доля секунды или что угодно по вашему выбору) вам нужно добавлять вектор между противником и игроком, умноженный на некоторую константу, к вашей скорости.

Velocity = Velocity + c * (Player-Enemy vector)

Константа c будет зависеть от того, насколько быстро вы хотите ускоряться по направлению к игроку и как часто вы обновляете свою скорость.

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

Velocity = Velocity * (Maximum magniture / |Velocity|)

РЕДАКТИРОВАТЬ: чтобы уточнить, добавление скорости просто означает добавление составляющих векторов. Итак,

Vx = Vx + c * Ax
Vy = Vy + c * Ay

где V - скорость, а A - ускорение. Величина измеряется как sqrt (Vx ^ 2 + Vy ^ 2) , то есть гипотенуза прямоугольного треугольника. Итак, если вы хотите, чтобы максимальная скорость врага была равна m,

Vx = Vx * ( m / sqrt(Vx^2 + Vy^2)
Vy = Vy * ( m / sqrt(Vx^2 + Vy^2)
2
ответ дан 7 December 2019 в 01:24
поделиться

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

Лучший способ сделать это - взять 2 радиан и lerp между ними, обрабатывая перенос. (возможно, путем добавления или вычитания 2pi, если необходимо). Затем преобразуйте его в единичный вектор. Затем умножьте это на скорость, с которой корабль разгоняется, и готово!

1
ответ дан 7 December 2019 в 01:24
поделиться

Подобные проблемы я решал профессионально и советую начинать с простых версий и работать над ними. Убедитесь, что вы получаете ожидаемое поведение на каждом этапе, прежде чем пробовать следующий.

  1. Искатель ищет неподвижную цель в начале координат в одном измерении. Правильно, одно измерение. Он может двигаться вперед и назад по оси x и пытается достичь x = 0. У двигателя нет дроссельной заслонки (как у твердотопливной ракеты), но искатель может направить его в любом направлении. Если вы запрограммируете это правильно, искатель будет колебаться около x = 0, каждый раз выходя за пределы.
  2. То же самое, но цель неподвижна где-то, кроме x = 0. Просто сделайте x относительным, а не абсолютным (то есть ищущий заботится о разнице в x, а не о x цели).
  3. Теперь цель движется (или прыгает). Ищущий должен иметь возможность следовать за ним. Колебания будут расти или уменьшаться в зависимости от того, как движется цель - вы поймете, что я имею в виду.
  4. Теперь два измерения. Искатель всегда направляется прямо к цели, что означает, что вы должны разделить тягу на компоненты x и y простым триггером. Если вы переместите цель, искатель может выйти на орбиту вокруг нее.
  5. Вернемся к одному измерению и к неподвижной цели, но теперь ищущий пытается встретиться, а не пролететь мимо. Это самая сложная часть. Цель состоит в том, чтобы расстояние и скорость стали равными нулю одновременно, без перескока, поэтому ищущий должен знать свои собственные тормозные способности. Когда x меньше v ^ 2 / 2a, искатель должен реверсировать тягу, отталкивая прочь от цели, чтобы замедлиться и встретить ее. Приятно позволить искателю прекратить колоть, когда он очень близко к цели.
  6. Цель снова начинает двигаться. Это просто; просто сделайте x и v относительными, а не абсолютными.
  7. Несколько измерений. Это удивительно просто; части x, y и z независимы.

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

1
ответ дан 7 December 2019 в 01:24
поделиться

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

Например, в небольшой 2-й игре, которую я написал ( http://wordwarvi.sourceforge.net ), есть «ракеты с тепловым наведением». Это выглядит довольно странно, если ракеты останавливаются в воздухе, чтобы развернуться. Я сделал следующее: я вычислил «желаемую скорость» по направлению к игроку. Это просто делается с помощью «похожих треугольников». Я нахожу расстояние до игрока в X и Y, и что больше,

1
ответ дан 7 December 2019 в 01:24
поделиться

Есть всего несколько указателей, чтобы сделать это правильно и легко. 1) проще всего работать с векторами, чем писать все два или три раза. 2) все будет выглядеть правильно, если вы управляете силой (которая фактически является ускорением, поскольку A = F / масса), а затем динамически изменяете скорость и положение.

Ваш основной цикл для реалистичного движения выглядит так (где CAP - векторы и dt - ваш временной шаг):

while (motion) {
   A = get_acceleration(X, V, A, X_target, V_targer, A_target)
   V += A*dt       // V is the integral of A
   X += V*dt       // X is the integral of V
}

И действительно, это все, потому что вы динамически эволюционируете.

Затем вам нужно решить, как определить ваше ускорение, то есть написать get_acceleration . Здесь есть несколько вариантов, которые зависят от множества факторов, и реальные охотники используют несколько стратегий. Например, если у вас большая тяга относительно вашей массы (т. Е. высокое ускорение) вы, вероятно, просто хотите лететь прямо в цель; но если у вас большая масса относительно вашей тяги, вы, вероятно, захотите выбрать курс на перехват. Если вы хотите замедлиться по мере приближения к цели, вы можете изменить ускорение, когда | X-X_target | станет маленьким (т.е. они приближаются) и / или их скорости близки. Кроме того, демпфирование может помочь вещам не колебаться, и для этого добавьте термин к ускорению, например -c * (V-V_target) . Я предлагаю вам поиграть с ними, пока вы не получите что-то, что соответствует внешнему виду и ощущениям, к которым вы стремитесь.

вы можете изменить ускорение, когда | X-X_target | станет маленьким (т.е. они приближаются) и / или их скорости близки. Кроме того, демпфирование может помочь вещам не колебаться, и для этого добавьте член к ускорению, например -c * (V-V_target) . Я предлагаю вам поиграть с ними, пока вы не получите что-то, что соответствует внешнему виду и ощущениям, к которым вы стремитесь.

вы можете изменить ускорение, когда | X-X_target | станет маленьким (т.е. они приближаются) и / или их скорости близки. Кроме того, демпфирование может помочь вещам не колебаться, и для этого добавьте термин к ускорению, например -c * (V-V_target) . Я предлагаю вам поиграть с ними, пока вы не получите что-то, что соответствует внешнему виду и ощущениям, к которым вы стремитесь.

1
ответ дан 7 December 2019 в 01:24
поделиться

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

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

while (game_in_progress)
{
    // Distance from enemy to player.  The larger the
    // distance, the greater the acceleration will be.
    delta.x = player.x - enemy.x
    delta.y = player.y - enemy.y

    // Accelerate by changing velocity based on distance,
    // where 'scale' is sufficiently small. (Limit v to
    // some maximum if you choose; likely to be unnecessary.)
    v.x += delta.x * scale
    v.y += delta.y * scale

    // Update the enemy's position.
    enemy.x += v.x
    enemy.y += v.y
}

Вычисляя значения x и y независимо, вы можете избавить себя от головной боли, связанной с векторами, углами и одновременным

Аналогичным образом, признавая, что ускорение (тяга) - это просто изменение скорости, которое, в свою очередь, является изменением положения,

2
ответ дан 7 December 2019 в 01:24
поделиться
Другие вопросы по тегам:

Похожие вопросы: