О чем этот пример
Создание динамичных визуальных эффектов, где множество объектов вращаются синхронно или по определенным правилам, — частая задача в разработке игр. Вручную обновлять угол каждого спрайта в массиве неэффективно и усложняет код. Плагин Actions в Phaser предоставляет мощные утилиты для групповой обработки игровых объектов. В этой статье мы разберем, как использовать метод `Phaser.Actions.Angle()` для плавного вращения целого массива спрайтов всего одной строкой кода, что идеально подходит для создания фоновой анимации, визуальных спецэффектов или "оживления" статичных элементов интерфейса.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
constructor ()
{
super();
this.gingerbreads = [];
}
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('gingerbread', 'assets/sprites/gingerbread.png');
}
create ()
{
for (let i = 0; i < 32; i++)
{
const x = Phaser.Math.Between(0, 800);
const y = Phaser.Math.Between(0, 600);
this.gingerbreads.push(this.add.image(x, y, 'gingerbread'));
}
}
update ()
{
Phaser.Actions.Angle(this.gingerbreads, 1);
}
}
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
backgroundColor: '#2d2d2d',
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Подготовка сцены и массива объектов
Для работы с группой объектов нам необходимо где-то их хранить. В конструкторе класса сцены инициализируется пустой массив gingerbreads, который будет содержать все наши спрайты.
В методе preload() загружается одно изображение, которое будет использовано для создания множества однотипных объектов.
Ключевой этап происходит в create(). Здесь в цикле создается 32 спрайта, каждый со случайными начальными координатами в пределах игрового поля. Каждый созданный спрайт немедленно добавляется в подготовленный массив.
class Example extends Phaser.Scene
{
constructor ()
{
super();
this.gingerbreads = []; // Инициализация массива для хранения объектов
}
preload ()
{
this.load.image('gingerbread', 'assets/sprites/gingerbread.png');
}
create ()
{
for (let i = 0; i < 32; i++)
{
const x = Phaser.Math.Between(0, 800);
const y = Phaser.Math.Between(0, 600);
// Создание спрайта и добавление его в массив
this.gingerbreads.push(this.add.image(x, y, 'gingerbread'));
}
}
Магия группового обновления: Phaser.Actions.Angle
Вся логика анимации заключена в методе update(), который вызывается на каждом кадре игры.
Метод Phaser.Actions.Angle() — это статическая функция, которая применяет изменение угла ко всем объектам в переданном массиве. Она принимает два основных аргумента:
1. Массив игровых объектов (в нашем случае this.gingerbreads).
2. Значение, на которое нужно изменить угол (в градусах). Мы передаем `1`.
Каждый кадр угол поворота каждого пряничного человечка в массиве будет увеличиваться на 1 градус. Это создает плавный эффект непрерывного вращения всех объектов.
update ()
{
// Увеличивает угол каждого объекта в массиве на 1 градус за кадр
Phaser.Actions.Angle(this.gingerbreads, 1);
}
Гибкость применения: от простого к сложному
Хотя пример демонстрирует простое постоянное вращение, возможности Phaser.Actions.Angle() гораздо шире. Второй параметр не обязательно должен быть константой.
Вы можете использовать математические функции Phaser или JavaScript, чтобы сделать вращение переменным. Например, можно сделать скорость вращения зависимой от положения объекта по оси X или привязать ее к синусоидальной функции времени, создавая волнообразный эффект.
Важно помнить, что метод изменяет свойство angle непосредственно у объектов в массиве. Это свойство использует градусы, в отличие от rotation, который использует радианы.
// Пример: скорость вращения зависит от позиции X объекта
Phaser.Actions.Angle(this.gingerbreads, function(obj) {
return obj.x * 0.01; // Объекты справа вращаются быстрее
});
// Пример: использование синуса для колебания скорости
let time = this.time.now;
Phaser.Actions.Angle(this.gingerbreads, Math.sin(time * 0.001) * 0.5);
Конфигурация и запуск игры
Код завершается стандартной для Phaser 3 конфигурацией игры. В объекте config задаются базовые параметры: тип рендерера, размеры холста, цвет фона, родительский HTML-элемент и класс основной сцены. После этого создается экземпляр игры new Phaser.Game(config), который запускает весь описанный жизненный цикл.
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
backgroundColor: '#2d2d2d',
parent: 'phaser-example',
scene: Example // Указываем наш класс сцены
};
const game = new Phaser.Game(config);
Что попробовать дальше
Метод Phaser.Actions.Angle — это элегантное и производительное решение для анимации угла поворота множества объектов. Он избавляет от необходимости писать циклы вручную и легко интегрируется в игровой цикл.
Для экспериментов попробуйте: изменить второй аргумент на отрицательное значение для вращения в другую сторону; применить Angle не каждый кадр, а по таймеру; комбинировать его с другими методами из модуля Actions, например Phaser.Actions.RotateAround, чтобы заставить объекты вращаться вокруг общей точки. Это откроет путь к созданию сложных и красивых паттернов движения.
