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

При создании сложных визуальных эффектов в Phaser разработчики часто используют контейнеры для группировки игровых объектов. Однако управление режимами наложения (blend modes) внутри контейнера имеет важную особенность: родительский контейнер может переопределять настройки своих детей. Эта статья объяснит, как правильно работать с режимами наложения в иерархии объектов, чтобы создавать именно те эффекты, которые вы задумали, без неожиданных визуальных артефактов.

Версия 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('grid', 'assets/pics/uv-grid-diag.png');
        this.load.image('logo', 'assets/sprites/phaser3-logo.png');
    }

    create ()
    {
        this.add.image(400, 300, 'grid');

        const image0 = this.add.image(0, -200, 'logo').setBlendMode(Phaser.BlendModes.ADD);
        const image1 = this.add.image(0, 0, 'logo').setBlendMode(Phaser.BlendModes.DIFFERENCE);
        const image2 = this.add.image(0, 200, 'logo').setBlendMode(Phaser.BlendModes.COLOR_DODGE);

        const container = this.add.container(400, 300, [ image0, image1, image2 ]);

        //  If the Container has a blend mode set it will override the children
        //  Un-comment the following line and the child blend modes will be replaced by the Containers

        // container.setBlendMode(Phaser.BlendModes.MULTIPLY);
    }
}

const config = {
    type: Phaser.CANVAS,
    width: 800,
    height: 600,
    backgroundColor: '#010101',
    parent: 'phaser-example',
    scene: Example
};

const game = new Phaser.Game(config);

Что такое режимы наложения и зачем они нужны

Режимы наложения (blend modes) определяют, как пиксели одного графического объекта смешиваются с пикселями объектов под ним. Phaser предоставляет множество режимов: ADD для свечения, MULTIPLY для затемнения, SCREEN для осветления и другие. Это мощный инструмент для создания спецэффектов без дополнительных текстур.

В примере мы видим три спрайта логотипа Phaser, каждый со своим режимом наложения, размещенные на фоновой сетке. Каждый спрайт создается независимо со своим blend mode.

Создание объектов и установка режимов наложения

Давайте разберем код создания спрайтов. Каждый спрайт логотипа создается как отдельный игровой объект с помощью метода this.add.image(). Сразу после создания для каждого спрайта вызывается метод .setBlendMode() с разным параметром.

const image0 = this.add.image(0, -200, 'logo').setBlendMode(Phaser.BlendModes.ADD);
const image1 = this.add.image(0, 0, 'logo').setBlendMode(Phaser.BlendModes.DIFFERENCE);
const image2 = this.add.image(0, 200, 'logo').setBlendMode(Phaser.BlendModes.COLOR_DODGE);

Ключевой момент: координаты (0, -200), (0, 0) и (0, 200) задаются относительно будущего родителя — контейнера. Это локальные координаты внутри контейнера.

Группировка объектов в контейнере

После создания трех спрайтов они группируются в контейнер. Контейнер — это особый игровой объект, который служит родителем для других объектов. Все трансформации (позиция, поворот, масштаб), применяемые к контейнеру, автоматически применяются ко всем его детям.

const container = this.add.container(400, 300, [ image0, image1, image2 ]);

Здесь мы создаем контейнер в мировых координатах (400, 300) и передаем массив с тремя созданными спрайтами. Теперь все три спрайта позиционируются относительно центра контейнера.

Важное правило: приоритет режима наложения контейнера

В коде примера есть закомментированная строка, которая демонстрирует ключевую механику Phaser. Если контейнеру самому установить режим наложения, он переопределит режимы наложения всех своих дочерних объектов.

// container.setBlendMode(Phaser.BlendModes.MULTIPLY);

Если раскомментировать эту строку, все три спрайта (image0, image1, image2) перестанут использовать свои индивидуальные режимы ADD, DIFFERENCE и COLOR_DODGE. Вместо этого они все будут отрисовываться с режимом MULTIPLY контейнера. Это поведение по умолчанию в Phaser: blend mode родительского контейнера имеет приоритет.

Практические рекомендации по использованию

1. **Для независимых эффектов:** Если каждому дочернему объекту нужен свой уникальный blend mode, не устанавливайте blend mode для контейнера-родителя. 2. **Для единого эффекта:** Если вся группа объектов должна взаимодействовать с фоном одинаково (например, вся группа светится), установите blend mode на контейнер. Это эффективнее, чем устанавливать одинаковый режим каждому ребенку вручную. 3. **Порядок отрисовки:** Помните, что контейнер отрисовывает своих детей в том порядке, в котором они были добавлены в массив. Это влияет на итоговое наложение пикселей друг на друга внутри контейнера.

Что попробовать дальше

Понимание иерархии режимов наложения — ключ к контролируемому созданию визуальных эффектов в Phaser. Используйте blend mode контейнера для унификации эффекта группы объектов и индивидуальные blend mode детей для сложных композиций. Для экспериментов попробуйте: анимировать положение контейнера, чтобы вся группа двигалась как единое целое с эффектами; применить разные blend mode к контейнеру и посмотреть, как это повлияет на смешение группы с динамическим фоном.