О чем этот пример

Контейнеры в 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 контейнера; вкладывать один контейнер в другой, наблюдая за наследованием свойств; или динамически добавлять и удалять дочерние объекты из контейнера во время выполнения игры.