Поскольку вы спрашивали об ускорении как векторе, здесь есть альтернативное решение, которое будет вычислять вещи таким образом.
Сначала, учитывая скорость (значение Vector2D
), давайте предположим, что вы можете вычислить направление из нее. Я не знаю ваш синтаксис, поэтому вот набросок того, что это может быть:
double forwardDirection = Math.toDegrees(velocity.direction()) + 90;
Это направление, куда указывает машина. (Автомобили всегда указывают в направлении своей скорости.)
Затем мы получаем компоненты ускорения. Во-первых, передняя и задняя часть ускорения, которая довольно проста:
double forwardAcceleration = 0;
if (up)
forwardAcceleration = 100;
if (down)
forwardAcceleration = -100;
Ускорение из-за рулевого управления немного сложнее. Если вы движетесь по кругу, величина ускорения к центру этого круга равна квадрату скорости, деленному на радиус круга. И, если вы поворачиваете налево, ускорение влево; если вы поворачиваете направо, то это направо. Итак:
double speed = velocity.magnitude();
double leftAcceleration = 0;
if (right)
leftAcceleration = ((speed * speed) / turningRadius);
if (left)
leftAcceleration = -((speed * speed) / turningRadius);
Теперь у вас есть значение forwardAcceleration
, которое содержит ускорение в прямом направлении (отрицательное для обратного), и значение leftAcceleration
, которое содержит ускорение в левом направлении (отрицательное для правого). Давайте преобразуем это в вектор ускорения.
Во-первых, некоторые дополнительные переменные направления, которые мы используем для создания единичных векторов (в первую очередь для упрощения объяснения кода):
double leftDirection = forwardDirection + 90;
double fDir = Math.toRadians(forwardDirection - 90);
double ldir = Math.toRadians(leftDirection - 90);
Vector2D forwardUnitVector = new Vector2D(Math.cos(fDir), Math.sin(fDir));
Vector2D leftUnitVector = new Vector2D(Math.cos(lDir), Math.sin(lDir));
Затем вы можете создать вектор ускорения, собрав переднюю и левую части, например:
Vector2D acceleration = forwardUnitVector.scale(forwardAcceleration);
acceleration = acceleration.add(leftUnitVector.scale(leftAcceleration));
Хорошо, это ваше ускорение. Вы конвертируете это в изменение скорости следующим образом (обратите внимание, что правильный термин для этого deltaV
, а не deltaA
):
Vector2D deltaV = acceleration.scale(secondsElapsed);
velocity = velocity.add(deltaV).
Наконец, вы, вероятно, хотите узнать, в каком направлении движется автомобиль (для того, чтобы нарисовать его на экране), поэтому вы вычисляете это по новой скорости:
double forwardDirection = Math.toDegrees(velocity.direction()) + 90;
И у вас это есть - физические вычисления выполняются с ускорением в виде вектора, а не с использованием одномерной скорости, которая вращается вместе с автомобилем.
(Эта версия ближе к тому, что вы изначально пытались сделать, поэтому позвольте мне немного проанализировать, в чем вы пошли не так. Часть ускорения, которая идет вверх / вниз, всегда в направлении, указанном автомобиль заострен, он не поворачивается вместе с рулевым механизмом до тех пор, пока автомобиль не поворачивает. Между тем, часть ускорения от рулевого управления всегда направлена только влево или вправо, и ее величина не имеет ничего общего с ускорением вперед / назад - и, в частности, его величина может быть ненулевой, даже если переднее / заднее ускорение равно нулю. Чтобы получить общий вектор ускорения, вам нужно вычислить эти две части отдельно и сложить их вместе как векторы.)
Ни одно из этих вычислений не является абсолютно точным. В этом примере вы вычисляете направления «вперед» и «влево» от того места, где началась машина, но автомобиль вращается, поэтому эти направления меняются с течением времени. Таким образом, уравнение deltaV = acceleration * time
является только оценочным и даст немного неправильный ответ. Другое решение имеет аналогичные неточности, но одна из причин того, что другое решение лучше, заключается в том, что в этом случае небольшие ошибки означают, что скорость будет увеличиваться, если вы будете управлять автомобилем влево и вправо, даже если вы этого не сделаете прикоснитесь к клавише «вверх» - тогда как в другой такой кросс-ошибки не происходит, потому что мы держим скорость и рулевое управление отдельно.