О чем этот пример
Контейнеры в Phaser — это мощный инструмент для группировки игровых объектов и централизованного управления их свойствами. В этой статье мы разберем, как устанавливать и анимировать прозрачность (`alpha`) для всего контейнера и его дочерних элементов. Это особенно полезно для создания сложных составных объектов (например, персонажа из нескольких спрайтов) и применения к ним общих визуальных эффектов, что упрощает код и повышает производительность.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
t = 0.0;
container;
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');
this.container = this.add.container(400, 300, [ image0, image1, image2, image3, image4 ]);
this.container.setAlpha(0.8);
image1.setAlpha(0.5);
image2.setAlpha(0.5);
image3.setAlpha(0.5);
image4.setAlpha(0.5);
this.tweens.add({
targets: this.container,
angle: 360,
duration: 6000,
yoyo: true,
repeat: -1
});
}
update ()
{
this.container.setAlpha(Math.abs(Math.sin(this.t)));
this.t += 0.01;
}
}
const config = {
type: Phaser.WEBGL,
width: 800,
height: 600,
backgroundColor: '#010101',
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Создание контейнера и добавление дочерних объектов
Контейнер (Container) — это игровой объект, который может содержать в себе другие игровые объекты. Координаты дочерних объектов задаются относительно позиции контейнера.
В методе create() сначала создаются пять изображений с леммингом. Их позиции заданы так, чтобы одно изображение было в центре, а четыре — по углам относительно центральной точки (0,0).
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');
Затем эти изображения передаются в конструктор контейнера. Первые два аргумента (400, 300) — это мировые координаты, где будет расположен центр контейнера на сцене.
this.container = this.add.container(400, 300, [ image0, image1, image2, image3, image4 ]);
Управление прозрачностью: контейнер vs дочерние объекты
Прозрачностью можно управлять как для всего контейнера целиком, так и для каждого дочернего объекта индивидуально. Значение alpha варьируется от 0 (полная прозрачность) до 1 (полная непрозрачность).
Сначала для всего контейнера устанавливается альфа-канал 0.8.
this.container.setAlpha(0.8);
Затем для четырех периферийных изображений устанавливается индивидуальная прозрачность 0.5. Важно понимать, что итоговая прозрачность каждого объекта вычисляется как произведение его собственного значения alpha и значения alpha всех его родительских контейнеров.
image1.setAlpha(0.5);
image2.setAlpha(0.5);
image3.setAlpha(0.5);
image4.setAlpha(0.5);
Таким образом, центральный image0 будет иметь прозрачность 0.8, а остальные четыре изображения — 0.8 * 0.5 = 0.4.
Анимация свойств контейнера
Одно из ключевых преимуществ контейнеров — возможность анимировать всю группу объектов как единое целое. В примере с помощью системы твинов создается бесконечная анимация вращения контейнера.
this.tweens.add({
targets: this.container,
angle: 360,
duration: 6000,
yoyo: true,
repeat: -1
});
Здесь targets — это наш контейнер, свойство angle изменяется до 360 градусов за 6000 миллисенд. Параметры yoyo: true и repeat: -1 заставляют анимацию проигрываться вперед-назад бесконечно.
Динамическое изменение прозрачности в реальном времени
Метод update() вызывается на каждом кадре игры и используется для динамического обновления состояния. В нашем примере прозрачность контейнера плавно пульсирует.
update ()
{
this.container.setAlpha(Math.abs(Math.sin(this.t)));
this.t += 0.01;
}
Значение this.t увеличивается на 0.01 каждый кадр. Функция Math.sin(this.t) возвращает значение от -1 до 1. Math.abs() преобразует его в диапазон от 0 до 1, что идеально подходит для свойства alpha. В результате контейнер и все его дочерние объекты плавно появляются и исчезают.
Что попробовать дальше
Контейнеры в Phaser — это фундаментальный инструмент для организации сложных игровых сущностей. Они позволяют централизованно управлять трансформациями (позиция, масштаб, вращение) и визуальными свойствами (прозрачность, видимость) группы объектов. Для экспериментов попробуйте: анимировать не только alpha, но и scaleX/scaleY контейнера; вкладывать один контейнер в другой, наблюдая за наследованием свойств; или динамически добавлять и удалять дочерние объекты из контейнера во время выполнения игры.
