О чем этот пример

При создании игр часто требуется перемещать объекты по заданным траекториям. Прямолинейное движение — простейший случай такой траектории. В этой статье разберем, как с помощью класса `Phaser.Curves.Line` не просто нарисовать линию, но и точно определить местоположение точки на ней, отступив определенное количество пикселей от начала. Этот прием незаменим для реализации плавного движения снарядов, путей патрулирования врагов или анимации интерфейсных элементов.

Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.

Живой запуск

Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.

Исходный код


class Example extends Phaser.Scene
{
    create ()
    {
        const graphics = this.add.graphics();

        const curve = new Phaser.Curves.Line(new Phaser.Math.Vector2(100, 200), new Phaser.Math.Vector2(600, 400));

        graphics.clear();
        graphics.lineStyle(2, 0xffffff, 1);

        curve.draw(graphics);

        //  Get the t value for 200 pixels along the curve
        const t = curve.getTFromDistance(200);

        //  Get the point at t
        const p = curve.getPoint(t);

        graphics.fillStyle(0xff0000, 1);
        graphics.fillCircle(p.x, p.y, 8);
    }
}

const config = {
    type: Phaser.AUTO,
    width: 800,
    height: 600,
    backgroundColor: '#2d2d2d',
    parent: 'phaser-example',
    scene: Example
};

const game = new Phaser.Game(config);

Создание линейной кривой

В основе примера лежит объект Phaser.Curves.Line. Несмотря на название, он представляет именно прямолинейный сегмент, что делает его вычисления быстрыми и точными.

Для создания кривой необходимо указать две точки в виде объектов Phaser.Math.Vector2: начальную и конечную. Эти векторы хранят координаты X и Y.

const curve = new Phaser.Curves.Line(
    new Phaser.Math.Vector2(100, 200),
    new Phaser.Math.Vector2(600, 400)
);

После создания кривую можно визуализировать, используя объект Graphics. Метод curve.draw(graphics) отрисует линию между заданными точками.

Ключевой метод: getTFromDistance

Параметр `t` в контексте кривых Phaser — это нормализованное значение от 0 до 1, где 0 соответствует началу кривой, а 1 — её концу.

Метод getTFromDistance(distance) — это то, что решает нашу задачу. Он принимает расстояние в пикселях от начала линии и возвращает соответствующее значение параметра `t`.

const t = curve.getTFromDistance(200);

В данном примере мы запрашиваем: "Какое значение `t` будет, если пройти 200 пикселей от стартовой точки (100, 200) вдоль линии к точке (600, 400)?". Метод производит внутренние расчеты на основе длины линии и возвращает число, например, 0.4.

Получение координат точки

Зная параметр `t, мы можем получить точные координаты (X, Y) на линии с помощью методаgetPoint(t)`.

const p = curve.getPoint(t);

Этот метод возвращает объект Phaser.Math.Vector2 с координатами искомой точки. В нашем случае это будет точка, расположенная в 200 пикселях от начала отрезка.

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

graphics.fillStyle(0xff0000, 1);
graphics.fillCircle(p.x, p.y, 8);

Практическое применение в игре

Рассмотрим, как эту технику можно использовать для движения спрайта.

1. **Инициализация:** Создайте кривую-линию, представляющую путь движения. 2. **Расчет позиции на кадре:** Внутри функции обновления (update) увеличивайте пройденное расстояние. Используйте getTFromDistance для получения текущего `t, а затемgetPoint(t)` для актуальных координат. 3. **Применение к спрайту:** Установите вычисленные координаты в положение спрайта.

// В create()
this.path = new Phaser.Curves.Line(startVec, endVec);
this.distanceTraveled = 0;
this.speed = 100; // пикселей в секунду

// В update(time, delta)
this.distanceTraveled += (this.speed * delta) / 1000;
const t = this.path.getTFromDistance(this.distanceTraveled);
const pos = this.path.getPoint(t);
this.playerSprite.setPosition(pos.x, pos.y);

Такой подход обеспечит плавное и математически точное движение объекта по прямой с постоянной скоростью.

Что попробовать дальше

Методы getTFromDistance и getPoint класса Phaser.Curves.Line предоставляют мощный и простой инструмент для управления движением по прямой. Они избавляют от необходимости вручную интерполировать координаты и работают с любой длиной и ориентацией отрезка. **Идеи для экспериментов:** 1. Реализуйте движение объекта «туда-обратно» по линии, изменяя направление при достижении конца. 2. Создайте очередь из нескольких линейных кривых (Phaser.Curves.Path), чтобы задать сложный ломаный маршрут для патруля, и используйте общее пройденное расстояние для навигации по нему. 3. Привяжите скорость движения к значению `t`, чтобы объект ускорялся в начале и замедлялся в конце пути.