О чем этот пример
Создание плавных и сложных траекторий для врагов, кат-сцен или спецэффектов — частая задача в разработке игр. Ручной расчет координат для каждой точки пути утомителен и негибок. В этой статье мы разберем, как на базе встроенного примера Phaser построить интерактивный визуальный редактор путей. Это позволит вам просто нарисовать нужную траекторию мышью и сразу использовать готовый массив точек в своем игровом коде, ускоряя прототипирование и дизайн уровней.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
const config = {
type: Phaser.AUTO,
width: window.innerWidth,
height: window.innerHeight,
backgroundColor: '#0055aa',
parent: 'phaser-example',
scene: Controller
};
const game = new Phaser.Game(config);
window.addEventListener('resize', function (event) {
game.resize(window.innerWidth, window.innerHeight);
}, false);
Исходный код и настройка сцены
Основная логика редактора находится в классе Controller, который мы передаем в конфигурацию игры. Давайте разберем ключевые элементы его конструктора.
class Controller extends Phaser.Scene {
constructor() {
super();
this.path = null;
this.graphics = null;
this.points = [];
this.curve = null;
this.dragging = false;
}
}
Здесь мы инициализируем свойства для хранения объекта пути (path), графического слоя для его отрисовки (graphics), массива опорных точек (points), кривой (curve) и флага перетаскивания.
Далее в методе create() происходит основная настройка. Создается Graphics объект — это наш холст для рисования линий и точек. Инициализируется объект Path, который будет управлять кривой.
this.graphics = this.add.graphics();
this.path = new Phaser.Curves.Path();
Обработка ввода: создание и перетаскивание точек
Интерактивность обеспечивается обработчиками событий мыши. При клике в любом месте сцены создается новая точка и добавляется в путь.
this.input.on('pointerdown', (pointer) => {
let point = new Phaser.Math.Vector2(pointer.x, pointer.y);
this.points.push(point);
this.redraw();
});
Функция redraw() очищает холст и заново рисует все точки и кривую. Для перетаскивания используется комбинация событий: когда курсор наведен на точку (pointerover), мы меняем его стиль и запоминаем индекс этой точки. При зажатии кнопки мыши (pointerdown) включается флаг dragging. Движение мыши с зажатой кнопкой (pointermove) обновляет координаты активной точки и перерисовывает сцену.
this.input.on('pointermove', (pointer) => {
if (this.dragging && this.activePointIndex !== null) {
this.points[this.activePointIndex].set(pointer.x, pointer.y);
this.redraw();
}
});
Построение и визуализация кривой
Сердце редактора — функция redraw(). Она выполняет три задачи:
1. Очистка предыдущего рисунка.
2. Построение пути из массива точек.
3. Отрисовка точек и сглаженной кривой.
Сначала мы очищаем графический слой и создаем новый Path.
this.graphics.clear();
this.path = new Phaser.Curves.Path();
Если точек больше двух, мы начинаем путь с первой точки, а затем для каждой последующей добавляем в путь линейный сегмент (Line). Если точка всего одна, путь начинается с нее.
if (this.points.length > 1) {
this.path.moveTo(this.points[0].x, this.points[0].y);
for (let i = 1; i < this.points.length; i++) {
this.path.lineTo(this.points[i].x, this.points[i].y);
}
} else if (this.points.length === 1) {
this.path.moveTo(this.points[0].x, this.points[0].y);
}
После построения пути мы визуализируем его. Рисуем точки как маленькие закрашенные круги, а сам путь — как линию. Метод draw объекта Path делает все вычисления за нас.
// Рисуем точки
this.graphics.fillStyle(0xff0000, 1);
for (let point of this.points) {
this.graphics.fillCircle(point.x, point.y, 6);
}
// Рисуем сам путь (кривую)
this.graphics.lineStyle(2, 0xffffff, 1);
this.path.draw(this.graphics);
Отладка и экспорт данных
Для практического использования редактора нам нужно получить готовый массив координат. В примере это реализовано через вывод в консоль. При нажатии клавиши 'D' (от англ. 'dump' — выгрузить) в консоль браузера выводится массив точек в удобном формате.
this.input.keyboard.on('keydown-D', () => {
console.log('Points Array:');
console.log(JSON.stringify(this.points.map(p => ({x: p.x, y: p.y})), null, 2));
});
Вы получите JSON, который можно скопировать и напрямую вставить в свой игровой код для создания идентичной траектории с помощью Phaser.Curves.Path или Phaser.Math.Interpolation. Это ключевой шаг, превращающий визуальный инструмент в часть рабочего процесса.
Что попробовать дальше
Вы построили интерактивный редактор путей, который превращает рутинную работу по расстановке координат в интуитивный процесс рисования. Готовый массив точек можно использовать для движения врагов по патрульным маршрутам, плавного перемещения камеры в кат-сценах или анимации UI-элементов.
**Идеи для экспериментов:**
1. Добавьте кнопки для удаления последней точки или очистки всего холста.
2. Реализуйте сохранение нескольких путей в localStorage для последующей загрузки.
3. Вместо линейных сегментов (lineTo) попробуйте использовать сплайны (spline) для создания более гладких, закругленных траекторий.
4. Создайте визуализацию движения объекта по построенному пути в реальном времени, используя метод path.getPoint. Это поможет сразу оценить результат.
