О чем этот пример
Анимация множества объектов — частый и эффектный приём в играх. В этом примере мы создадим сетку из 108 блоков, которые будут плавно увеличиваться, поворачиваться и возвращаться в исходное состояние в шахматном порядке. Этот подход полезен для создания фоновых анимаций, визуальных эффектов интерфейса или оживления игрового поля.
Версия 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/tweens/space.png');
this.load.image('block', 'assets/sprites/50x50.png');
}
create ()
{
this.add.image(400, 300, 'bg');
const blocks = this.add.group({ key: 'block', repeat: 107, setScale: { x: 0.1, y: 0.1 } });
Phaser.Actions.GridAlign(blocks.getChildren(), {
width: 12,
height: 9,
cellWidth: 60,
cellHeight: 60,
x: 40,
y: 30
});
let i = 0;
blocks.children.forEach(child => {
this.tweens.add({
targets: child,
scale: 1,
angle: 180,
ease: 'Power2',
duration: 1000,
delay: i * 50,
repeat: -1,
yoyo: true,
hold: 1000,
repeatDelay: 1000
});
i++;
if (i % 12 === 0)
{
i = 0;
}
});
}
}
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
backgroundColor: '#2d2d2d',
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Подготовка сцены и загрузка ресурсов
Класс Example расширяет Phaser.Scene и содержит стандартные методы жизненного цикла сцены.
В методе preload() мы задаём базовый URL для загрузки и загружаем два изображения: фоновую картинку 'bg' и спрайт блока 'block'. Эти ресурсы будут использоваться для визуализации.
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('bg', 'assets/tweens/space.png');
this.load.image('block', 'assets/sprites/50x50.png');
Создание группы объектов и их выравнивание
В методе create() сначала добавляется фоновое изображение.
Затем создаётся группа (Group) под названием blocks. Группа — это удобный контейнер для управления множеством однотипных объектов. Параметр key указывает текстуру для всех объектов группы. Параметр repeat: 107 говорит о том, что всего объектов будет 108 (исходный + 107 повторений). setScale задаёт начальный масштаб каждому создаваемому спрайту.
const blocks = this.add.group({ key: 'block', repeat: 107, setScale: { x: 0.1, y: 0.1 } });
Далее используется статический метод Phaser.Actions.GridAlign для автоматического расположения всех детей группы в сетку 12x9. Параметры cellWidth и cellHeight задают размер ячейки, а `xиy` — начальное смещение сетки.
Phaser.Actions.GridAlign(blocks.getChildren(), {
width: 12,
height: 9,
cellWidth: 60,
cellHeight: 60,
x: 40,
y: 30
});
Настройка анимации для каждого спрайта
После размещения объектов в сетку мы проходимся по всем детям группы с помощью forEach.
Для каждого ребёнка (child) создаётся твин (tween) — объект, управляющий плавной анимацией свойств. Твин создаётся через this.tweens.add().
this.tweens.add({
targets: child,
scale: 1,
angle: 180,
ease: 'Power2',
duration: 1000,
delay: i * 50,
repeat: -1,
yoyo: true,
hold: 1000,
repeatDelay: 1000
});
Ключевые параметры твина:
- targets: объект, который будет анимироваться.
- scale и angle: целевые значения масштаба (до 1) и угла поворота (180 градусов).
- ease: функция плавности анимации.
- duration: длительность одного цикла анимации (в миллисекундах).
- delay: задержка перед стартом анимации для данного объекта. Она рассчитывается как i * 50, что создаёт эффект волны или шахматного порядка.
- repeat: -1: анимация повторяется бесконечно.
- yoyo: true: после завершения цикла анимация проигрывается в обратном порядке.
- hold: пауза в конце прямого цикла перед началом обратного.
- repeatDelay: пауза между полными циклами (прямой + обратный).
Создание шахматного порядка задержек
Переменная `iиспользуется для расчёта задержки (delay) для каждого спрайта. После обработки каждого спрайтаi` увеличивается на единицу.
Условие if (i % 12 === 0) сбрасывает счётчик `i` обратно в 0, когда обработано 12 спрайтов (ширина нашей сетки). Это означает, что задержки будут повторяться для каждого нового ряда, создавая характерный волнообразный или шахматный паттерн анимации.
let i = 0;
blocks.children.forEach(child => {
// ... создание твина с delay: i * 50 ...
i++;
if (i % 12 === 0)
{
i = 0;
}
});
Конфигурация и запуск игры
В конце файла определяется конфигурационный объект config для экземпляра игры Phaser.Game. В нём задаются основные параметры: тип рендерера, размеры холста, цвет фона, ID родительского HTML-элемента и класс основной сцены.
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
backgroundColor: '#2d2d2d',
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
После создания экземпляра game Phaser автоматически начнёт выполнение жизненного цикла сцены.
Что попробовать дальше
Мы разобрали пример, который демонстрирует мощь комбинации Group, Phaser.Actions для управления множеством объектов и Tweens для создания сложных повторяющихся анимаций. Для экспериментов попробуйте изменить параметры сетки (например, width и height), поиграть со значениями delay, hold и repeatDelay в твинах, или заменить анимируемые свойства — например, анимируйте alpha (прозрачность) или `x,y` (позицию).
