О чем этот пример
Создание естественных и плавных траекторий — ключевой элемент визуального качества игры. Прямолинейное движение выглядит механически, в то время как кривые Безье позволяют задавать органичные пути для снарядов, врагов или UI-элементов. В этой статье мы разберем, как использовать квадратичную кривую Безье в Phaser для анимации объекта. Вы научитесь создавать кривую по опорным точкам, визуализировать её и плавно перемещать спрайт по заданному пути с помощью встроенного tween-движка.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
graphics;
curve;
path;
create ()
{
this.graphics = this.add.graphics();
this.path = { t: 0, vec: new Phaser.Math.Vector2() };
const startPoint = new Phaser.Math.Vector2(100, 500);
const controlPoint1 = new Phaser.Math.Vector2(50, 100);
const endPoint = new Phaser.Math.Vector2(700, 500);
this.curve = new Phaser.Curves.QuadraticBezier(startPoint, controlPoint1, endPoint);
this.tweens.add({
targets: this.path,
t: 1,
ease: 'Sine.easeInOut',
duration: 2000,
yoyo: true,
repeat: -1
});
}
update ()
{
this.graphics.clear();
this.graphics.lineStyle(1, 0x00ff00, 1);
this.curve.draw(this.graphics);
this.curve.getPoint(this.path.t, this.path.vec);
this.graphics.fillStyle(0xff0000, 1);
this.graphics.fillCircle(this.path.vec.x, this.path.vec.y, 16);
}
}
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
backgroundColor: '#2d2d2d',
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Подготовка сцены и создание кривой
Вся логика примера содержится в классе сцены. В методе create мы подготавливаем объекты: создаем контейнер для рисования (Graphics), определяем структуру для хранения позиции на кривой и, самое главное, создаем саму кривую.
Квадратичная кривая Безье определяется тремя точками: начальной, контрольной и конечной. Контрольная точка не лежит на кривой, но "притягивает" её к себе, формируя плавный изгиб.
this.graphics = this.add.graphics();
this.path = { t: 0, vec: new Phaser.Math.Vector2() };
const startPoint = new Phaser.Math.Vector2(100, 500);
const controlPoint1 = new Phaser.Math.Vector2(50, 100);
const endPoint = new Phaser.Math.Vector2(700, 500);
this.curve = new Phaser.Curves.QuadraticBezier(startPoint, controlPoint1, endPoint);
Анимация параметра пути с помощью Tween
Чтобы объект двигался по кривой, нам нужно изменять параметр `tот 0 (начало кривой) до 1 (конец кривой). Для этого идеально подходит система твинов Phaser. Мы анимируем свойствоtвнутри нашего объектаthis.path`.
Tween настроен на плавное (ease) движение туда и обратно (yoyo) с бесконечным повторением. Значение `t` будет автоматически меняться движком в каждом кадре.
this.tweens.add({
targets: this.path,
t: 1,
ease: 'Sine.easeInOut',
duration: 2000,
yoyo: true,
repeat: -1
});
Визуализация кривой и объекта в Update
Метод update вызывается каждый кадр. Здесь мы выполняем три действия: очищаем предыдущее рисование, рисуем саму кривую для наглядности и вычисляем текущую позицию объекта на ней.
Сначала очищаем Graphics от старой отрисовки. Затем задаем стиль линии и рисуем кривую с помощью метода curve.draw. После этого, используя текущее значение this.path.t, получаем координаты точки на кривой в вектор this.path.vec. Эти координаты используем для отрисовки красного круга, изображающего движущийся объект.
this.graphics.clear();
this.graphics.lineStyle(1, 0x00ff00, 1);
this.curve.draw(this.graphics);
this.curve.getPoint(this.path.t, this.path.vec);
this.graphics.fillStyle(0xff0000, 1);
this.graphics.fillCircle(this.path.vec.x, this.path.vec.y, 16);
Конфигурация игры и запуск
Финальный шаг — стандартная конфигурация игры Phaser. В ней мы указываем базовые настройки, такие как размер холста, цвет фона и связываем конфиг с созданным классом нашей сцены. После этого создается и запускается экземпляр игры.
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
backgroundColor: '#2d2d2d',
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Что попробовать дальше
Кривые Безье — мощный инструмент для создания сложного движения из простых компонентов. Вы можете заменить красный круг на спрайт врага или снаряда, использовать несколько кривых для составного пути или динамически менять контрольные точки в реальном времени, чтобы траектория реагировала на действия игрока.
Для экспериментов попробуйте изменить координаты контрольной точки, чтобы увидеть, как резко меняется форма кривой. Или замените QuadraticBezier на CubicBezier, которая использует две контрольные точки для еще более гибких траекторий.
