О чем этот пример
Создание плавных и органичных путей движения — ключевая задача в разработке игр. Будь то полёт снаряда, патрулирование врага или анимация интерфейса, кривые Безье предлагают элегантное решение. В этой статье мы разберём, как использовать кубические кривые Безье в Phaser 3 для построения сложных траекторий и, что особенно важно, как получать с них дискретные точки. Это открывает двери для расчёта столкновений, позиционирования объектов и создания пошагового движения.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
create ()
{
const graphics = this.add.graphics();
const p0 = new Phaser.Math.Vector2(100, 500);
const p1 = new Phaser.Math.Vector2(50, 100);
const p2 = new Phaser.Math.Vector2(600, 100);
const p3 = new Phaser.Math.Vector2(700, 500);
const curve = new Phaser.Curves.CubicBezier(p0, p1, p2, p3);
graphics.lineStyle(1, 0xffffff, 1);
curve.draw(graphics, 64);
// Get 32 points from the curve
const points = curve.getPoints(32);
// Draw the points
graphics.fillStyle(0x00ff00, 1);
for (let i = 0; i < points.length; i++)
{
graphics.fillCircle(points[i].x, points[i].y, 6);
}
}
}
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
backgroundColor: '#2d2d2d',
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Создание кривой: четыре точки судьбы
Кубическая кривая Безье определяется четырьмя опорными точками. Две из них — это начало и конец кривой (p0 и p3). Две другие (p1 и p2) — это контрольные точки, которые "притягивают" кривую, задавая её форму. В Phaser для этого используется класс Phaser.Curves.CubicBezier.
const p0 = new Phaser.Math.Vector2(100, 500);
const p1 = new Phaser.Math.Vector2(50, 100);
const p2 = new Phaser.Math.Vector2(600, 100);
const p3 = new Phaser.Math.Vector2(700, 500);
const curve = new Phaser.Curves.CubicBezier(p0, p1, p2, p3);
Здесь мы создаём кривую, которая начинается внизу слева (100, 500), резко уходит вверх к контрольным точкам, а затем плавно опускается вниз справа (700, 500).
Визуализация: рисуем кривую на сцене
Чтобы увидеть нашу кривую, нужно её нарисовать. Для этого используется объект Graphics. Мы задаём стиль линии и метод draw самой кривой, который принимает контекст отрисовки и количество отрезков для аппроксимации кривой.
const graphics = this.add.graphics();
graphics.lineStyle(1, 0xffffff, 1);
curve.draw(graphics, 64);
Параметр 64 в методе curve.draw указывает, на сколько линейных сегментов разбить кривую для отрисовки. Чем выше значение, тем более гладкой будет выглядеть кривая, особенно если она сложная.
Получение точек: ключ к интерактивности
Самая мощная часть API — метод getPoints(divisions). Он возвращает массив объектов Vector2, равномерно распределённых по длине кривой. Количество точек равно параметру divisions + 1.
const points = curve.getPoints(32);
Этот вызов вернёт 33 точки (32 сегмента + начальная точка). Эти точки — не просто для отображения. Они представляют собой дискретное представление траектории, которое можно использовать для: * Пошагового перемещения объекта по кривой. * Проверки столкновений объекта с элементами на пути. * Размещения нескольких объектов (например, монет или врагов) вдоль пути.
Практическое применение: от траектории до игры
Давайте нарисуем полученные точки, чтобы визуализировать результат. Это поможет понять, как объект будет "шагать" по пути.
graphics.fillStyle(0x00ff00, 1);
for (let i = 0; i < points.length; i++)
{
graphics.fillCircle(points[i].x, points[i].y, 6);
}
С этим массивом точек вы можете, например, в цикле обновления состояния игры (update) перемещать спрайт от одной точки к следующей, создавая иллюзию плавного движения по сложной траектории. Это гораздо эффективнее, чем пересчитывать позицию по формуле Безье каждый кадр.
Что попробовать дальше
Кубические кривые Безье в Phaser — это мощный инструмент для работы с нелинейными траекториями. Метод getPoints превращает математическую абстракцию в практический набор данных для игровой логики. Для экспериментов попробуйте: анимировать движение спрайта по точкам, изменять контрольные точки в реальном времени в ответ на действия игрока или создать систему пулевого расчёта, где траектория снаряда рассчитывается один раз в виде точек для оптимизации.
