Как рассчитать точки на линии с интервалами - PullRequest
0 голосов
/ 19 декабря 2018

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

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

Вот мой код на данный момент:

animationFrame = refresh;
    double x, y, xPerF; //Values for drawing
    double m, b; //Value for slope and y-intercept
    double x1, x2, y1, y2; //Values for the targets
    x1 = getCenterX();
    x2 = Canvas.target[shotTarget].getCenterX();
    y1 = getCenterY();
    y2 = Canvas.target[shotTarget].getCenterY();
    xPerF = Point2D.distance(x1, y1, x2, y2)/animationSpeed;
    //Calculate slope
    if(x2>x1) m = (y2-y1)/(x2-x1);
    else if(x2<x1) m = (y1-y2)/(x1-x2);
    else m = 0;
    //Calculate the y-intercept
    b = m * x1 - y1;
    if(b<0) b = -b + Canvas.myHeight;
    else {
        b -= Canvas.myHeight;
        if(b<0) b = -b;
    }
    //Calculate the x value
    if(x1>x2) x = x1 - (xPerF * animationFrame);
    else if(x1<x2) x = x1 + (xPerF * animationFrame);
    else x = x1;
    //Calculate the y value
    if(m!=0) y = (m * x + b) - Canvas.myHeight;
    else {
        if(y1>y2) y = y1 - (xPerF * animationFrame);
    else y = y1 + (xPerF * animationFrame);
    }
    g.fillOval((int) x - 15, (int) y - 15, 30, 30);
    //Debugging
    System.out.println("Frame " + animationFrame + " of " + animationSpeed + " | " + y + " = " + m + " * " + x + " + " + b + " | at speed of " + xPerF);

Обновлено

Я ожидаю, что анимация заканчивается в целевом местоположении, но она всегда либо переходит, либо находится прямо на цели,Он в основном перекрывает, когда цель довольно прямо над башней, дает или берет несколько x координат.Я решил, что это плоскость квадрата 1 xy, и я считаю, что проблема, с которой я столкнулся сейчас, заключается в том, как я вычисляю свой наклон.Спасибо!

Устаревший

Вот мини-апплет для демонстрации: https://drive.google.com/file/d/1fCTFJzulY1fcBUmdV6AXOd7Ol1g9B3lo/view?usp=sharing

Нажмите на каждую цель, чтобы нацелиться на нее

Ответы [ 2 ]

0 голосов
/ 21 декабря 2018

Ответ

Я понял это.Вместо того, чтобы вычислять координаты методом перехвата наклона, я просто вычислял интервалы, которые мне нужно было бы увеличивать по y и x на кадр, и увеличивал их на основе кадра анимации.

double x, y, xPerF, yPerF; //Values for drawing
double x1, x2, y1, y2; //Values for the targets
x1 = getCenterX();
x2 = Canvas.target[shotTarget].getCenterX();
y1 = getCenterY();
y2 = Canvas.target[shotTarget].getCenterY();
xPerF = (Math.max(x1, x2) - Math.min(x1, x2))/animationSpeed;
yPerF = (Math.max(y1, y2) - Math.min(y1, y2))/animationSpeed;
if(x1>x2) x = x1 - xPerF * animationFrame;
else if(x1<x2) x = x1 + xPerF * animationFrame;
else x = x1;
if(y1>y2) y = y1 - yPerF * animationFrame;
else if(y1<y2) y = y1 + yPerF * animationFrame;
else y = y1;
g.fillOval((int) x - 15, (int) y - 15, 30, 30);
0 голосов
/ 20 декабря 2018

Я считаю, что ваш подход в корне ошибочен.Это склонно к ошибкам округления, которые могут быть источником для выбросов.Также трудно добиться хорошей работы в реальном мире, где ваше приложение не единственное, поэтому процессор может быть востребован, некоторые кадры могут быть пропущены и т. Д.Лучшим подходом является использование времени, а не кадров, в качестве основного фактора событий.Ваш основной метод drawScene принимает текущее время в качестве одного из аргументов.Когда запускается любая анимация, вы экономите время ее запуска.Тогда работа становится намного проще.Например, для линейной анимации это будет примерно так:

double animationPart = (currentTime - animationStartTime) / totalAnimationDuration;
// fix rounding error
if (animationPart > 1.0)
    animationPart = 1.0; 

double xCur = xStart * (1.0 - animationPart) + xEnd * animationPart;
double yCur = yStart * (1.0 - animationPart) + yEnd * animationPart;

PS «время» не обязательно должно быть реальным временем, это может быть какое-то другое «игровое время», если оно каким-то образом имеет больше смыслано все же этот подход ИМХО намного проще реализовать правильно.


Обновление

Я бы сказал, что общее качество кода довольно плохое.Проблемы плохо разделены, есть много магических чисел и глобальных статических вещей.Например, использование двух пуль в полете будет нелегко реализовать в этом коде.

В коде анимации также есть некоторые реальные ошибки.Вот некоторые очевидные ошибки:

  1. xPerF рассчитано неверно.Вы разделяете евклидово расстояние, а не просто разницу в координате X.

  2. Логика для y ошибочна.По крайней мере, вы должны добавить m * (x - x1) вместо m * x.Но это все равно не будет охватывать случай вертикальной съемки (т.е. случай, когда X-координата вообще не изменяется).Если вы хотите пойти по этому пути, вы должны использовать xPerF и yPerF и избавиться от m и связанных с ним if.

Это может или не может исправить проблемы с анимацией (в списке у вас все еще есть вероятность ошибок округления).Я бы все еще сказал, что изменение вашего shoot на что-то вроде

public void shootTarget(int target) {
    shotTarget = target;
    shotTime = animationFrame;
}

и затем использование

double animationPart = ((double) (animationFrame - shotTime)) / animationSpeed;

, как предложено выше, является лучшим способом.Примечание: это всего лишь заглушка, потому что в вашем реальном коде вы по какой-то причине регулярно присваиваете 0 для refresh и, следовательно, animationFrame, так что это не будет работать так просто.

...