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

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

Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.55.2.

Живой запуск

Ниже встроен рабочий билд примера. Оригинальный источник: 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 particles = this.add.particles('gems');

        const emitter = particles.createEmitter({
            anim: { anims: [ 'prism', 'square' ], cycle: true },
            x: 64,
            y: { start: 500, end: 100, steps: 8 },
            lifespan: 4000,
            accelerationX: 200,
            frequency: 100
        });

        console.log(particles);
        console.log(emitter);
    }
}

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

const game = new Phaser.Game(config);

Подготовка ассетов: загрузка атласа

В основе анимированных частиц лежит спрайтовый лист (атлас) с последовательностью кадров. Phaser позволяет загрузить его с помощью метода this.load.atlas(). В нашем примере атлас 'gems' состоит из изображения и JSON-файла с координатами фреймов.

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');

Метод setBaseURL задает базовый URL для всех последующих загрузок, что удобно для указания корневой папки с ресурсами. Ключ 'gems' будет использоваться для доступа к атласу в коде.

Создание анимаций из кадров атласа

После загрузки атласа необходимо создать анимации, которые сможет проигрывать наш эмиттер. Для этого используется менеджер анимаций this.anims. Метод this.anims.create() регистрирует новую анимацию с уникальным ключом.

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

Критически важную роль играет функция this.anims.generateFrameNames(). Она автоматически генерирует массив кадров, обращаясь к атласу 'gems' и находя в нём все фреймы по заданному шаблону. Параметры prefix (префикс имени), end (последний номер кадра) и zeroPad (дополнение номера нулями слева) позволяют гибко указать нужную последовательность. Параметр repeat: -1 заставляет анимацию зацикливаться бесконечно.

Инициализация системы частиц и эмиттера

Система частиц в Phaser — это контейнер для одного или нескольких эмиттеров. Создадим систему, указав тот же ключ атласа 'gems', который будет использоваться как текстура для частиц.

const particles = this.add.particles('gems');

Далее создаем сам эмиттер с помощью метода createEmitter(). Его конфигурация определяет поведение и внешний вид частиц.

const emitter = particles.createEmitter({
    anim: { anims: [ 'prism', 'square' ], cycle: true },
    x: 64,
    y: { start: 500, end: 100, steps: 8 },
    lifespan: 4000,
    accelerationX: 200,
    frequency: 100
});

Конфигурация эмиттера: анимация и физика

Разберем ключевые параметры конфигурационного объекта эмиттера.

**Анимация частиц (anim):** Это сердце нашего эффекта. Мы передаем объект с массивом anims, содержащим ключи созданных ранее анимаций ('prism', 'square'). Параметр cycle: true указывает, что каждая новая частица будет брать следующую анимацию из массива по циклу, создавая визуальное разнообразие.

anim: { anims: [ 'prism', 'square' ], cycle: true }

**Положение и движение:** Параметр `xфиксирует координату по горизонтали. Параметрy` задан объектом, что позволяет создать дискретный набор стартовых позиций: от 500 до 100 пикселей с 8 шагами. Это формирует вертикальную линию из 8 точек, из которых будут вылетать частицы.

**Прочие параметры:** lifespan задает время жизни частицы в миллисекундах (4000 мс = 4 секунды). accelerationX определяет ускорение по оси X, заставляя частицы двигаться вправо с нарастающей скоростью. frequency устанавливает интервал между испусканием частиц (100 мс).

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

Комбинирование системы частиц и анимаций открывает огромный простор для творчества. Вы можете создавать не просто движущиеся точки, а живые, переливающиеся эффекты. Для экспериментов попробуйте: изменить массив anims на все четыре созданные анимации ('diamond', 'prism', 'ruby', 'square'); заменить cycle: true на random: true для случайного выбора анимации; анимировать другие параметры эмиттера, например, менять accelerationX или angle в течение времени жизни частицы, используя функции-генераторы.