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

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

Версия 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);

        //  Our emitter
        const emitter = this.add.particles(0, 0, 'lemming', {
            lifespan: 2000,
            speed: { min: 200, max: 400 },
            angle: 330,
            gravityY: 300
        });

        container.add(emitter);

        //  Rotate the container
        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);

Зачем добавлять эмиттер в контейнер?

Обычно система частиц, созданная через this.add.particles(), существует в мировых координатах сцены. Добавив её в контейнер, вы «привязываете» её к локальной системе координат этого контейнера.

Это означает, что все свойства трансформации контейнера — его позиция, угол поворота (angle), масштаб — автоматически применяются и к испускаемым частицам. Частицы будут рождаться относительно центра контейнера и вращаться вместе с ним, что невозможно при независимом размещении эмиттера.

Разбор кода: создание контейнера и эмиттера

В методе create() сцены происходит основная настройка. Сначала создаётся пустой контейнер в центре экрана.

const container = this.add.container(400, 300);

Затем создаётся эмиттер частиц. Обратите внимание, что его начальные координаты (0, 0) теперь будут отсчитываться не от мирового начала координат, а от позиции контейнера, в который мы его позже поместим.

const emitter = this.add.particles(0, 0, 'lemming', {
    lifespan: 2000,
    speed: { min: 200, max: 400 },
    angle: 330,
    gravityY: 300
});

Ключевой момент — добавление эмиттера в контейнер с помощью метода .add(). Теперь эмиттер становится дочерним объектом контейнера.

container.add(emitter);

Анимация целой системы

Сила этого подхода раскрывается при анимации. Мы применяем твин (плавную анимацию) не к эмиттеру, а ко всему контейнеру.

this.tweens.add({
    targets: container,
    angle: 360,
    duration: 6000,
    yoyo: true,
    repeat: -1
});

Твин вращает контейнер на 360 градусов. Поскольку эмиттер теперь часть контейнера, весь поток частиц также будет плавно вращаться по кругу, создавая эффект вихря или спирали. Параметры yoyo: true и repeat: -1 заставляют анимацию проигрываться в прямом и обратном направлении бесконечно.

Конфигурация игры и важные детали

Пример использует стандартную конфигурацию игры. Обратите внимание на backgroundColor: '#010101' — тёмный фон помогает лучше видеть светлые частицы.

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

Важное замечание по API: метод this.add.particles() создаёт и возвращает объект типа ParticleEmitterManager. При добавлении в контейнер передаётся именно этот менеджер. Все его эмиттеры (в данном случае один) наследуют трансформации контейнера.

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

Добавление эмиттера частиц в контейнер — это простой, но мощный приём для создания сложных связанных визуальных эффектов в Phaser. Вы можете экспериментировать: добавьте в этот же контейнер спрайт корабля, чтобы частицы имитировали выхлоп, или разместите несколько контейнеров с разными эмиттерами для создания многослойного анимированного фона. Попробуйте анимировать не только angle, но и свойства scaleX, scaleY контейнера, чтобы частицы динамически меняли размер вместе с родительской группой.