О чем этот пример
Работа с множеством игровых объектов по отдельности может быть утомительной и неэффективной. Phaser предлагает мощное решение — контейнеры (`Container`), которые позволяют объединять спрайты, изображения и другие объекты в единую группу. Это не только упрощает управление трансформациями (перемещение, вращение, масштабирование), но и повышает производительность, сокращая количество обращений к рендереру. В этой статье мы разберем, как создавать контейнеры, добавлять в них объекты и применять анимации ко всей группе сразу.
Версия 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 ()
{
// Create some images
// Positions are relative to the Container x/y
const image0 = this.add.image(0, 0, 'lemming');
const image1 = this.add.image(-100, -100, 'lemming');
const image2 = this.add.image(100, -100, 'lemming');
const image3 = this.add.image(100, 100, 'lemming');
const image4 = this.add.image(-100, 100, 'lemming');
const container = this.add.container(400, 300, [ image0, image1, image2, image3, image4 ]);
this.tweens.add({
targets: container,
angle: 360,
duration: 6000,
yoyo: true,
repeat: -1
});
}
}
const config = {
type: Phaser.CANVAS,
width: 800,
height: 600,
backgroundColor: '#010101',
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Что такое контейнер и зачем он нужен?
Контейнер (Container) в Phaser — это специальный игровой объект, который служит родительским контейнером для других объектов. Все дочерние элементы наследуют трансформации (положение, угол поворота, масштаб) от своего родителя. Это означает, что перемещая или вращая контейнер, вы автоматически перемещаете или вращаете все объекты внутри него относительно его точки привязки.
Основные преимущества использования контейнеров: - **Упрощение логики**: вместо управления каждым объектом по отдельности вы управляете одной сущностью. - **Оптимизация производительности**: движок обрабатывает контейнер как единый элемент отрисовки. - **Групповые трансформации**: легко применять анимации и изменения ко всей группе.
Создание и наполнение контейнера
В примере мы видим, как создать несколько изображений и поместить их в контейнер. Ключевой метод — this.add.container(x, y, children), где `xиy— координаты контейнера на сцене, аchildren` — массив дочерних объектов.
Обратите внимание: координаты дочерних изображений задаются **относительно позиции контейнера**. Например, изображение с координатами (-100, -100) будет расположено на 100 пикселей выше и левее центра контейнера.
const image0 = this.add.image(0, 0, 'lemming');
const image1 = this.add.image(-100, -100, 'lemming');
const image2 = this.add.image(100, -100, 'lemming');
const image3 = this.add.image(100, 100, 'lemming');
const image4 = this.add.image(-100, 100, 'lemming');
const container = this.add.container(400, 300, [ image0, image1, image2, image3, image4 ]);
После этого контейнер становится самостоятельным объектом на сцене, который можно анимировать или перемещать.
Анимация контейнера с помощью Tween
Одна из самых мощных возможностей контейнеров — применение анимаций ко всей группе объектов через систему Tween. В примере используется this.tweens.add(), чтобы создать бесконечную анимацию вращения контейнера на 360 градусов.
this.tweens.add({
targets: container,
angle: 360,
duration: 6000,
yoyo: true,
repeat: -1
});
Параметры:
- targets: указывает на контейнер, который нужно анимировать.
- angle: целевое значение угла поворота (в градусах).
- duration: длительность анимации в миллисекундах.
- yoyo: если true, анимация проигрывается в обратном направлении после завершения.
- repeat: количество повторений (-1 для бесконечного повтора).
В результате все пять изображений вращаются как единое целое вокруг точки (400, 300), сохраняя свои относительные позиции.
Настройка сцены и запуск игры
Для запуска примера необходимо настроить конфигурацию игры (config) и создать экземпляр Phaser.Game. В конфигурации указывается тип рендерера, размеры холста, цвет фона и класс сцены.
const config = {
type: Phaser.CANVAS,
width: 800,
height: 600,
backgroundColor: '#010101',
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Это стандартная структура для любого проекта на Phaser. Класс Example расширяет Phaser.Scene и содержит методы preload() для загрузки ресурсов и create() для создания игровых объектов.
Практические советы по работе с контейнерами
1. **Используйте контейнеры для сложных объектов**: например, для персонажа, состоящего из нескольких спрайтов (тело, оружие, анимации).
2. **Управляйте видимостью и активностью**: отключение контейнера (container.setActive(false)) скрывает все дочерние элементы.
3. **Вложенные контейнеры**: контейнеры могут содержать другие контейнеры, что позволяет создавать иерархические структуры.
4. **Сортировка по глубине**: используйте container.setDepth(), чтобы управлять порядком отрисовки группы объектов.
5. **Осторожно с маской**: применение маски к контейнеру затрагивает все дочерние элементы, что может быть полезно для эффектов обрезки.
Что попробовать дальше
Контейнеры в Phaser — это мощный инструмент для организации игровых объектов в логические группы. Они упрощают код, повышают производительность и открывают возможности для сложных анимаций. Попробуйте экспериментировать: создайте контейнер для интерфейса (кнопки, панели), реализуйте параллакс-эффект с несколькими слоями или постройте иерархию объектов для RPG-персонажа с экипировкой.
