Перемещение точки вдоль линии в JavaScript Canvas - PullRequest
12 голосов
/ 13 мая 2011

Допустим, у меня есть координаты линии (25,35 45,65, 30,85 - это будет линия из двух частей).Мне нужно перемещать точку (автомобиль) вдоль этой линии на постоянном расстоянии каждый кадр.Как я могу это сделать?

Ответы [ 3 ]

18 голосов
/ 13 мая 2011

Эй, у вас есть координаты (25,35) (45,65) (30,85) для ваших двух линий. Точка, которую вы хотите переместить, будет помещена в первую из этих координат (25,35), и вы хотите, чтобы он двигался ко второй координате (45,65) (конец первого отрезка).

Первый шаг - получить ориентацию, в которой будет перемещаться точка,ориентация - это угол между позицией точки и позицией цели.Чтобы найти этот угол, вы можете использовать Math.atan2(), передавая в качестве первого аргумента target position Y - the point position Y, а в качестве второго аргумента target position X - the point position X.

var Point = {X: 25, Y: 35};
var Target = {X:45, Y:65};

var Angle = Math.atan2(Target.Y - Point.Y, Target.X - Point.X);

Теперь получите синус и косинус этогоугол, синус - это значение для перемещения по оси Y, а косинус - это то, сколько нужно двигаться по оси X.Умножьте синус и косинус на расстояние, которое вы хотите переместить каждый кадр.

var Per_Frame_Distance = 2;
var Sin = Math.sin(Angle) * Per_Frame_Distance;
var Cos = Math.cos(Angle) * Per_Frame_Distance;

Хорошо, осталось сделать только метод перерисовки, где вы добавляете синус в позицию Y точки икосинус к точке X позиции при каждом вызове.Проверьте, прибыла ли точка к месту назначения, затем выполните тот же процесс, чтобы перейти к концу второго отрезка.

11 голосов
/ 13 мая 2011

Рассмотрим строку (25,35 45,65). Вектор от начала до конца равен (20, 30). Чтобы переместить точку (x, y) в этом направлении, мы могли бы просто добавить этот вектор:

V = (20, 30) (x, y) => (x + 20, y + 30).

Если мы начнем с начала строки, мы придем к концу. Но это слишком большой шаг. Мы хотим что-то меньшее, но в том же направлении, поэтому мы умножаем вектор, скажем, на 0,1:

V = (2, 3) (x, y) => (x + 2, y + 3) => (x + 4, y + 6) => ...

Удобно нормализовать , то есть сделать его длину 1, что мы делим на его длину:

V => V / | V | = (2,3) / sqrt (2 2 + 3 2 ) = (7,21, 10,82)

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

1 голос
/ 17 августа 2016

Иногда не так очевидно, как перевести математическую формулу в код. Ниже приведена реализация функции, которая перемещает точку на определенное расстояние вдоль линии. Используются векторные обозначения:

function travel(x, y, dx, x1, y1, x2, y2)
{
    var point = new Vector(x, y),
        begin = new Vector(x1, y1),
        end = new Vector(x2, y2);
    return end.sub(begin).norm().mul(dx).add(point);
}

class Vector
{
    constructor(x = 0, y = 0) {
        this.x = x;
        this.y = y;
    }

    clone() {
        return new this.constructor(this.x, this.y);
    }

    add(v) {
        this.x += v.x;
        this.y += v.y;
        return this;
    }

    sub(v) {
        this.x = this.x - v.x;
        this.y = this.y - v.y;
        return this;
    }

    mul(x) {
        this.x *= x;
        this.y *= x;
        return this;
    }

    div(x) {
        this.x /= x;
        this.y /= x;
        return this;
    }

    get mag() {
        return Math.sqrt(this.x * this.x + this.y * this.y);
    }

    norm() {
        var mag = this.mag;
        if (mag > 0) {
            this.div(mag);
        }
        return this;
    }
}

И версия без Vector класс:

function travel(x, y, dx, x1, y1, x2, y2)
{
    var a = {x: x2 - x1, y: y2 - y1},
        mag = Math.sqrt(a.x*a.x + a.y*a.y);
    if (mag == 0) {
        a.x = a.y = 0;
    }
    else {
        a.x = a.x/mag*dx;
        a.y = a.y/mag*dx;
    }
    return {x: x + a.x, y: y + a.y};
}
...