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

Частицы — ключевой элемент визуальных эффектов в играх. Статические точки или картинки выглядят скучно. В Phaser 3 Particle Emitter позволяет использовать анимации из атласа в качестве частиц, создавая сложные и динамичные эффекты вроде магических вспышек, сверкающих звёзд или падающих листьев. Эта статья покажет, как настроить анимацию для частиц, используя код из официальных примеров Phaser, и объяснит тонкости конфигурации.

Версия 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.atlas('gems', 'assets/tests/columns/gems.png', 'assets/tests/columns/gems.json');
    }

    create ()
    {
        this.anims.create({ key: 'diamond', frames: this.anims.generateFrameNames('gems', { prefix: 'diamond_', end: 15, zeroPad: 4 }), repeat: -1 });
        this.anims.create({ key: 'prism', frames: this.anims.generateFrameNames('gems', { prefix: 'prism_', end: 6, zeroPad: 4 }), repeat: -1 });
        this.anims.create({ key: 'ruby', frames: this.anims.generateFrameNames('gems', { prefix: 'ruby_', end: 6, zeroPad: 4 }), repeat: -1 });
        this.anims.create({ key: 'square', frames: this.anims.generateFrameNames('gems', { prefix: 'square_', end: 14, zeroPad: 4 }), repeat: -1 });

        const emitter = this.add.particles(400, 100, 'gems', {
            // anim: [ 'diamond', 'prism', 'square', 'ruby' ],
            // anim: 'diamond',
            // anim: { anims: [ 'diamond', 'prism', 'ruby' ], cycle: true, quantity: 100 },
            anim: { anims: { key: 'ruby', randomFrame: true } },
            speed: 100,
            lifespan: 6000,
            gravityY: 120
        });

        console.log(emitter);
        console.log(emitter.anims);

        // this.tweens.add({
        //     targets: emitter,
        //     x: 600,
        //     yoyo: true,
        //     repeat: -1,
        //     duration: 2000,
        //     ease: 'sine.inout'
        // });
    }
}

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

const game = new Phaser.Game(config);

Подготовка анимаций для частиц

Перед созданием эмиттера необходимо загрузить атлас с текстурами и создать анимации. В примере используется атлас 'gems' с несколькими типами драгоценных камней. Каждая анимация создаётся методом this.anims.create. Ключевой момент — использование this.anims.generateFrameNames для автоматической генерации кадров по шаблону имени.

this.anims.create({
    key: 'diamond',
    frames: this.anims.generateFrameNames('gems', {
        prefix: 'diamond_',
        end: 15,
        zeroPad: 4
    }),
    repeat: -1
});

Параметр prefix задаёт начало имени кадра (например, 'diamond_0001'), end определяет последний номер кадра, а zeroPad: 4 добавляет ведущие нули до четырёх знаков. repeat: -1 заставляет анимацию проигрываться бесконечно. Мы создали четыре анимации: 'diamond', 'prism', 'ruby' и 'square'.

Создание эмиттера с анимированными частицами

Эмиттер частиц создаётся через this.add.particles. Первые два аргумента — стартовые координаты X и Y. Третий аргумент — ключ текстуры или атласа ('gems'). Четвёртый аргумент — объект конфигурации эмиттера.

const emitter = this.add.particles(400, 100, 'gems', {
    anim: { anims: { key: 'ruby', randomFrame: true } },
    speed: 100,
    lifespan: 6000,
    gravityY: 120
});

Свойство anim отвечает за анимацию частиц. В этом примере используется сложная форма записи: объект, внутри которого свойство anims содержит другой объект с ключом key (имя анимации 'ruby') и флагом randomFrame. Это означает, что каждая частица будет проигрывать анимацию 'ruby', но начнёт с произвольного кадра, создавая разнообразие. Без randomFrame все частицы стартовали бы синхронно с первого кадра.

Базовые параметры: speed (скорость разлёта), lifespan (время жизни частицы в миллисекундах), gravityY (симуляция гравитации).

Варианты настройки свойства `anim`

Свойство anim эмиттера очень гибкое. В закомментированном коде примера показаны разные способы его использования.

**1. Одна анимация для всех частиц:**

anim: 'diamond'

Все частицы будут проигрывать анимацию 'diamond' с первого кадра.

**2. Массив анимаций для случайного выбора:**

anim: [ 'diamond', 'prism', 'square', 'ruby' ]

Каждая новая частица случайно получит одну из четырёх анимаций.

**3. Циклический перебор анимаций с заданным количеством:**

anim: { anims: [ 'diamond', 'prism', 'ruby' ], cycle: true, quantity: 100 }

Частицы будут получать анимации по порядку из массива anims, цикличность обеспечивается cycle: true. Параметр quantity, вероятно, управляет тем, сколько частиц используют одну анимацию перед переходом к следующей (требует проверки в документации).

Выбор варианта зависит от нужного эффекта: однородный поток, хаотичное смешение или упорядоченная последовательность.

Отладка и управление эмиттером

После создания эмиттера полезно заглянуть в его структуру. В примере эмиттер и его свойство anims выводятся в консоль.

console.log(emitter);
console.log(emitter.anims);

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

this.tweens.add({
    targets: emitter,
    x: 600,
    yoyo: true,
    repeat: -1,
    duration: 2000,
    ease: 'sine.inout'
});

Твин анимирует свойство `xэмиттера от начального значения до 600 пикселей и обратно (yoyo: true) бесконечно (repeat: -1) с плавной синусоидальной функцией плавности (ease`).

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

Использование анимаций в Particle Emitter Phaser 3 превращает стандартные частицы в живые, сложные визуальные эффекты. Экспериментируйте: комбинируйте разные анимации в одном эмиттере, настраивайте randomFrame для разнообразия, анимируйте положение и другие свойства самого эмиттера через tweens. Попробуйте привязать эмиттер к спрайту игрока для эффектов ауры или движения, или создайте взрыв, где частицы-осколки проигрывают анимацию разрушения.