О чем этот пример
Анимации движения по орбитам — это основа визуальной динамики в играх, от космических симуляторов до магических заклинаний. В этой статье мы разберем, как создать эффектную систему вращающихся объектов по изменяющейся орбите, используя всего несколько строчек кода Phaser. Вы научитесь управлять группами объектов, применять геометрические фигуры для размещения и связывать физику движения с анимациями Tween для создания живых, интерактивных сцен.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
constructor ()
{
super();
}
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('bg', 'assets/skies/space3.png');
this.load.image('star', 'assets/demoscene/ball-tlb.png');
}
create ()
{
this.add.image(400, 300, 'bg');
const stars = this.add.group({ key: 'star', repeat: 32 });
const circle = new Phaser.Geom.Circle(400, 300, 64);
Phaser.Actions.PlaceOnCircle(stars.getChildren(), circle);
this.tweens.add({
targets: circle,
radius: 228,
ease: 'Quintic.easeInOut',
duration: 1500,
yoyo: true,
repeat: -1,
onUpdate: function ()
{
Phaser.Actions.RotateAroundDistance(stars.getChildren(), { x: 400, y: 300 }, 0.02, circle.radius);
}
});
}
}
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
backgroundColor: '#2d2d2d',
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Структура сцены и загрузка ресурсов
Начнем с базовой настройки сцены, как и в любом проекте на Phaser. Класс Example расширяет Phaser.Scene.
В методе preload мы загружаем два изображения: фоновую текстуру (bg) и спрайт (star), который будет выступать в роли нашего вращающегося объекта. Обратите внимание, что setBaseURL задает базовый путь для удобства, но в реальном проекте вы, скорее всего, будете использовать локальные пути.
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('bg', 'assets/skies/space3.png');
this.load.image('star', 'assets/demoscene/ball-tlb.png');
}
Создание группы объектов и геометрической основы
В методе create мы сначала размещаем фоновое изображение. Затем создаем группу (Group) спрайтов. Группа — это мощный инструмент Phaser для управления коллекцией игровых объектов. Мы создаем 32 повторения спрайта 'star' одним вызовом.
Ключевой элемент — создание экземпляра Phaser.Geom.Circle. Этот круг определяет начальную орбиту для наших объектов с центром в точке (400, 300) и радиусом 64 пикселя.
const stars = this.add.group({ key: 'star', repeat: 32 });
const circle = new Phaser.Geom.Circle(400, 300, 64);
С помощью статического метода Phaser.Actions.PlaceOnCircle мы мгновенно размещаем все дочерние элементы группы stars на окружности нашего круга. Каждый спрайт займет равномерно распределенную позицию по ее периметру.
Phaser.Actions.PlaceOnCircle(stars.getChildren(), circle);
Анимация орбиты с помощью Tween
Самая интересная часть — анимация. Мы создаем твин (Tween), который будет анимировать не спрайты напрямую, а наш геометрический круг! Объектом анимации (targets) выступает переменная circle.
Конфигурация твина говорит ему изменить радиус круга от начального значения (64) до 228 пикселей за 1500 миллисенд, используя плавную функцию ease. Параметры yoyo: true и repeat: -1 заставляют анимацию играть вперед-назад бесконечно.
this.tweens.add({
targets: circle,
radius: 228,
ease: 'Quintic.easeInOut',
duration: 1500,
yoyo: true,
repeat: -1,
onUpdate: function ()
{
// Код обновления позиции спрайтов
}
});
Связывание движения объектов с анимацией круга
Магия происходит в колбэке onUpdate. Этот функция вызывается на каждом кадре анимации твина. Внутри нее мы обновляем позиции наших спрайтов, чтобы они следовали за изменяющейся орбитой.
Метод Phaser.Actions.RotateAroundDistance выполняет две операции одновременно для всех объектов в массиве:
1. **Вращает** каждый спрайт вокруг центральной точки ({ x: 400, y: 300 }) на фиксированный угол (0.02 радиана за кадр). Это создает непрерывное круговое движение.
2. **Устанавливает расстояние** от спрайта до центра вращения равным текущему радиусу анимированного круга (circle.radius). Именно это заставляет орбиту пульсировать.
Phaser.Actions.RotateAroundDistance(stars.getChildren(), { x: 400, y: 300 }, 0.02, circle.radius);
Таким образом, твин управляет геометрией (радиусом), а RotateAroundDistance синхронно применяет эти изменения к позициям спрайтов, создавая идеально синхронизированный эффект.
Конфигурация и запуск игры
Финал — стандартная конфигурация игры Phaser. Мы указываем тип рендерера, размеры холста, цвет фона (который будет перекрыт нашим изображением bg) и корневой класс сцены.
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
backgroundColor: '#2d2d2d',
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Что попробовать дальше
Вы только что создали сложную на вид, но элегантную по реализации систему орбитального движения. Сила этого подхода — в разделении ответственности: геометрическая фигура хранит состояние (радиус), твин его анимирует, а метод Actions применяет изменения к группе объектов. Для экспериментов попробуйте: заменить круг на Phaser.Geom.Ellipse для эллиптических орбит, анимировать не радиус, а координаты центра круга, привязать угол вращения в RotateAroundDistance к скорости движения игрока или менять текстуру спрайтов в зависимости от их позиции на орбите.
