О чем этот пример
При создании игр часто требуется перемещать объекты по заданным траекториям. Прямолинейное движение — простейший случай такой траектории. В этой статье разберем, как с помощью класса `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`, чтобы объект ускорялся в начале и замедлялся в конце пути.
