О чем этот пример
Работа с большим количеством игровых объектов может превратиться в рутину. Вам нужно двигать, вращать или масштабировать каждую единицу отдельно, что усложняет код и снижает производительность. Контейнеры Phaser решают эту проблему, позволяя управлять группой объектов как единым целым. В этой статье мы разберем, как создавать контейнеры, добавлять в них спрайты и применять анимации ко всей группе сразу. Этот подход идеально подходит для создания сложных составных объектов, интерфейсов или управления множеством однотипных элементов, таких как частицы или элементы окружения.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('lemming', 'assets/sprites/lemming.png');
}
create ()
{
// Our container
const container = this.add.container(400, 300);
// Add some sprites - positions are relative to the Container x/y
const sprite0 = this.add.sprite(0, 0, 'lemming');
const sprite1 = this.add.sprite(-100, -100, 'lemming');
const sprite2 = this.add.sprite(100, -100, 'lemming');
const sprite3 = this.add.sprite(100, 100, 'lemming');
const sprite4 = this.add.sprite(-100, 100, 'lemming');
container.add(sprite0);
container.add(sprite1);
container.add(sprite2);
container.add(sprite3);
container.add(sprite4);
// You could also pass them in as an array, to save doing them one by one
this.tweens.add({
targets: container,
angle: 360,
duration: 6000,
yoyo: true,
repeat: -1
});
}
}
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
backgroundColor: '#010101',
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Создание контейнера и добавление спрайтов
Контейнер (Container) — это особый тип игрового объекта, который может выступать в роли родителя для других объектов. Все дочерние объекты наследуют его трансформации (положение, угол поворота, масштаб). Это похоже на работу с папками в графическом редакторе: перемещая папку, вы перемещаете все её содержимое.
В методе create() мы создаем контейнер и несколько спрайтов. Ключевой момент: координаты спрайтов задаются относительно позиции контейнера.
// Our container
const container = this.add.container(400, 300);
// Add some sprites - positions are relative to the Container x/y
const sprite0 = this.add.sprite(0, 0, 'lemming');
const sprite1 = this.add.sprite(-100, -100, 'lemming');
const sprite2 = this.add.sprite(100, -100, 'lemming');
const sprite3 = this.add.sprite(100, 100, 'lemming');
const sprite4 = this.add.sprite(-100, 100, 'lemming');
Спрайт sprite0 будет находиться прямо в центре контейнера (400, 300 на игровом холсте), а sprite1 — на 100 пикселей выше и левее этого центра. После создания объекты по одному добавляются в контейнер с помощью метода .add().
container.add(sprite0);
container.add(sprite1);
// ... и так далее для всех спрайтов
Эффективное добавление объектов
Phaser предоставляет более компактный способ добавления нескольких дочерних элементов за один вызов — передачу массива объектов. Это делает код чище и удобнее для чтения, особенно когда объектов много.
// You could also pass them in as an array, to save doing them one by one
container.add([sprite0, sprite1, sprite2, sprite3, sprite4]);
Оба способа — и по одному, и массивом — функционально идентичны. Выбор зависит от стиля и удобства. Например, если спрайты создаются в цикле и складываются в массив, логичнее добавить их сразу всем массивом.
Анимация контейнера
Самая мощная особенность контейнеров проявляется при анимации. Вместо того чтобы настраивать твин для каждого спрайта, мы применяем его к самому контейнеру. Все дочерние спрайты унаследуют эту анимацию.
В примере используется система твинов Phaser (this.tweens.add). Мы анимируем свойство angle контейнера.
this.tweens.add({
targets: container, // Цель анимации — наш контейнер
angle: 360, // Конечное значение: полный оборот
duration: 6000, // Длительность анимации в миллисекундах
yoyo: true, // Анимация проиграется в обратном порядке после завершения
repeat: -1 // Бесконечное повторение
});
В результате все пять спрайтов, прикрепленных к контейнеру, начнут плавно вращаться вокруг общей точки (400, 300), образуя единую вращающуюся композицию. Свойства yoyo и repeat делают анимацию непрерывной и плавной.
Порядок отрисовки и вложенность
Объекты внутри контейнера отрисовываются в том порядке, в котором они были добавлены. Первый добавленный спрайт окажется "ниже" (ближе к фону), а последний — "сверху". Порядок можно менять динамически с помощью методов контейнера, таких как moveTo, bringToTop или sendToBack.
Контейнеры могут быть вложенными. Вы можете добавить один контейнер как дочерний объект в другой. Это открывает возможности для создания сложных иерархических структур, например, персонажа (контейнер верхнего уровня), у которого есть отдельный контейнер для оружия, который, в свою очередь, содержит спрайты дула и прицела.
const playerContainer = this.add.container(100, 100);
const weaponContainer = this.add.container(0, 0); // Относительно playerContainer
const barrel = this.add.sprite(20, 0, 'barrel');
weaponContainer.add(barrel);
playerContainer.add(weaponContainer);
// Теперь вращение playerContainer повлияет и на weaponContainer, и на barrel.
Конфигурация игры и запуск сцены
Код примера завершается стандартной для Phaser конфигурацией игры и её инициализацией. В конфиге указывается наша сцена Example.
const config = {
type: Phaser.AUTO, // Рендерер: WebGL или Canvas
width: 800,
height: 600,
backgroundColor: '#010101', // Темный фон для контраста
parent: 'phaser-example', // ID HTML-элемента для встраивания
scene: Example // Класс главной сцены
};
const game = new Phaser.Game(config);
Это базовая конфигурация, достаточная для запуска примера. В реальных проектах сюда часто добавляют настройки физики (physics), масштабирования (scale) или несколько сцен.
Что попробовать дальше
Контейнеры — это фундаментальный инструмент для организации кода и логики в Phaser. Они позволяют мыслить группами объектов, а не одиночными единицами, что упрощает управление сложными сценами. Для экспериментов попробуйте
- Анимировать не только
angle, но иscaleилиalphaконтейнера - Создать интерфейс с кнопками (спрайтами) внутри контейнера и двигать его целиком
- Реализовать систему частиц, где контейнер управляет всей группой частиц, а каждая частица также имеет свою небольшую анимацию
