О чем этот пример
Создание сложных геометрических паттернов и динамичных вращающихся структур — частая задача в игровой разработке. Вместо того чтобы вручную рассчитывать позиции для каждого спрайта, Phaser предоставляет мощные утилиты в модуле `Actions`. Эта статья покажет, как использовать `Phaser.Actions.PlaceOnCircle` и `Phaser.Actions.RotateAroundDistance` для быстрого размещения группы объектов по окружности и придания им плавного орбитального движения. Этот подход идеально подходит для создания эффектов ауры, круговых интерфейсов, планетарных систем или просто визуально приятных заставок.
Версия 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('ball', 'assets/sprites/shinyball.png');
}
create ()
{
this.group1 = this.add.group({ key: 'ball', frameQuantity: 16 });
this.group2 = this.add.group({ key: 'ball', frameQuantity: 16 });
this.group3 = this.add.group({ key: 'ball', frameQuantity: 16 });
this.group4 = this.add.group({ key: 'ball', frameQuantity: 16 });
Phaser.Actions.PlaceOnCircle(this.group1.getChildren(), { x: 400, y: 300, radius: 200 });
Phaser.Actions.PlaceOnCircle(this.group2.getChildren(), { x: 400, y: 300, radius: 160 });
Phaser.Actions.PlaceOnCircle(this.group3.getChildren(), { x: 400, y: 300, radius: 120 });
Phaser.Actions.PlaceOnCircle(this.group4.getChildren(), { x: 400, y: 300, radius: 80 });
}
update ()
{
Phaser.Actions.RotateAroundDistance(this.group1.getChildren(), { x: 400, y: 300 }, 0.02, 200);
Phaser.Actions.RotateAroundDistance(this.group2.getChildren(), { x: 400, y: 300 }, 0.02, 160);
Phaser.Actions.RotateAroundDistance(this.group3.getChildren(), { x: 400, y: 300 }, 0.02, 120);
Phaser.Actions.RotateAroundDistance(this.group4.getChildren(), { x: 400, y: 300 }, 0.02, 80);
}
}
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
backgroundColor: '#2d2d2d',
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Подготовка сцены и создание групп спрайтов
Вся логика примера содержится в классе сцены Example. В методе preload загружается одно изображение мяча, которое будет использовано для всех спрайтов.
Ключевой этап происходит в create. Здесь создаются четыре группы спрайтов (Group) с помощью метода this.add.group. Каждая группа сразу заполняется 16-ю экземплярами спрайта 'ball' (параметр frameQuantity). Группы в Phaser — это удобный способ управления коллекциями игровых объектов.
this.group1 = this.add.group({ key: 'ball', frameQuantity: 16 });
this.group2 = this.add.group({ key: 'ball', frameQuantity: 16 });
this.group3 = this.add.group({ key: 'ball', frameQuantity: 16 });
this.group4 = this.add.group({ key: 'ball', frameQuantity: 16 });
Размещение объектов по окружности: PlaceOnCircle
После создания групп все спрайты находятся в одной точке. Чтобы распределить их, используется статический метод Phaser.Actions.PlaceOnCircle. Он принимает массив объектов (в нашем случае — результат вызова group.getChildren()) и объект конфигурации, описывающий окружность.
Конфигурация включает центр окружности (`x,y) и ееradius`. Метод равномерно распределяет все переданные объекты по полной окружности (360 градусов). В примере мы создаем четыре концентрические окружности с разными радиусами.
Phaser.Actions.PlaceOnCircle(this.group1.getChildren(), { x: 400, y: 300, radius: 200 });
Phaser.Actions.PlaceOnCircle(this.group2.getChildren(), { x: 400, y: 300, radius: 160 });
Phaser.Actions.PlaceOnCircle(this.group3.getChildren(), { x: 400, y: 300, radius: 120 });
Phaser.Actions.PlaceOnCircle(this.group4.getChildren(), { x: 400, y: 300, radius: 80 });
Анимация вращения: RotateAroundDistance
Статическое расположение — это только начало. Чтобы оживить композицию, в методе update (вызываемом каждый кадр) применяется Phaser.Actions.RotateAroundDistance. Этот метод вращает массив объектов вокруг заданной точки.
Он принимает массив объектов, точку вращения (объект с `xиy), угол поворота в радианах за вызов и исходное расстояние от объектов до центра (радиус). Важно передавать тот жеradius`, что и при размещении, чтобы объекты оставались на своей орбите и не "спиралились" к центру или от него. Положительное значение угла (0.02) задает вращение против часовой стрелки.
Phaser.Actions.RotateAroundDistance(this.group1.getChildren(), { x: 400, y: 300 }, 0.02, 200);
Phaser.Actions.RotateAroundDistance(this.group2.getChildren(), { x: 400, y: 300 }, 0.02, 160);
// ... и так далее для каждой группы
Настройка игры (Config) и запуск
Работа Phaser-приложения начинается с конфигурационного объекта, который передается в конструктор Phaser.Game. В этом примере используется базовая конфигурация:
- type: Phaser.AUTO позволяет Phaser самому выбрать рендерер (WebGL или Canvas).
- width и height: устанавливают размер игрового поля.
- backgroundColor: цвет фона в HEX-формате.
- parent: ID HTML-элемента, в который будет встроен canvas.
- scene: класс главной сцены, которая будет запущена сразу.
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
backgroundColor: '#2d2d2d',
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Что попробовать дальше
Методы PlaceOnCircle и RotateAroundDistance из модуля Actions — это мощный и лаконичный инструмент для создания сложных круговых анимаций без необходимости писать тригонометрические расчеты вручную. Для экспериментов попробуйте изменить количество спрайтов в группах, угловую скорость вращения (например, сделать внутренние круги быстрее внешних) или динамически менять радиус в update, чтобы создать эффект "пульсации". Также можно комбинировать эти действия с другими, например SetAlpha или SetTint, для создания более ярких визуальных эффектов.
