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

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

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

    create ()
    {
        const flame = this.add.particles(150, 550, 'flares',
        {
            frame: 'white',
            color: [ 0xfacc22, 0xf89800, 0xf83600, 0x9f0404 ],
            colorEase: 'quad.out',
            lifespan: 2400,
            angle: { min: -100, max: -80 },
            scale: { start: 0.70, end: 0, ease: 'sine.out' },
            speed: 100,
            advance: 2000,
            blendMode: 'ADD'
        });

        const wisp = this.add.particles(400, 550, 'flares',
        {
            frame: 'white',
            color: [ 0x96e0da, 0x937ef3 ],
            colorEase: 'quart.out',
            lifespan: 1500,
            angle: { min: -100, max: -80 },
            scale: { start: 1, end: 0, ease: 'sine.in' },
            speed: { min: 250, max: 350 },
            advance: 2000,
            blendMode: 'ADD'
        });

        const smokey = this.add.particles(650, 550, 'flares',
        {
            frame: 'white',
            color: [ 0x040d61, 0xfacc22, 0xf89800, 0xf83600, 0x9f0404, 0x4b4a4f, 0x353438, 0x040404 ],
            lifespan: 1500,
            angle: { min: -100, max: -80 },
            scale: 0.75,
            speed: { min: 200, max: 300 },
            advance: 2000,
            blendMode: 'ADD'
        });
    }
}

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

const game = new Phaser.Game(config);

Загрузка атласа частиц

В основе всех наших эффектов лежит один спрайт-лист (атлас) под названием 'flares'. Он содержит различные текстуры для частиц, но мы будем использовать только один кадр — 'white'. Это белый квадрат, который мы затем будем окрашивать программно. Такой подход экономит ресурсы и дает полный контроль над цветом.

this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.atlas('flares', 'assets/particles/flares.png', 'assets/particles/flares.json');

Создание цветного пламени

Первый эмиттер имитирует языки пламени. Ключевой параметр здесь — color. Мы передаем массив из четырех hex-цветов. Частицы будут плавно перетекать из одного цвета в другой по заданной кривой (colorEase). Параметр advance ускоряет стартовую фазу жизни частицы, создавая эффект «выстрела».

const flame = this.add.particles(150, 550, 'flares',
{
    frame: 'white',
    color: [ 0xfacc22, 0xf89800, 0xf83600, 0x9f0404 ], // От желтого к темно-красному
    colorEase: 'quad.out',
    lifespan: 2400,
    angle: { min: -100, max: -80 }, // Летят вверх и немного в стороны
    scale: { start: 0.70, end: 0, ease: 'sine.out' }, // Плавное исчезновение
    speed: 100,
    advance: 2000,
    blendMode: 'ADD' // Режим наложения «Добавление» для свечения
});

Эффект холодного огонька (wisp)

Второй эмиттер создает эффект магического или холодного пламени. Обратите внимание на два отличия от первого: более холодная палитра цветов и случайная скорость (speed: { min: 250, max: 350 }). Это делает частицы более «живыми» и непредсказуемыми. Кривая colorEase: 'quart.out' обеспечивает более резкий переход цвета в начале жизни частицы.

const wisp = this.add.particles(400, 550, 'flares',
{
    frame: 'white',
    color: [ 0x96e0da, 0x937ef3 ], // От голубого к фиолетовому
    colorEase: 'quart.out',
    lifespan: 1500,
    angle: { min: -100, max: -80 },
    scale: { start: 1, end: 0, ease: 'sine.in' }, // Исчезновение по кривой 'in'
    speed: { min: 250, max: 350 }, // Случайная скорость
    advance: 2000,
    blendMode: 'ADD'
});

Имитация густого дыма

Третий эмиттер создает эффект дыма от огня. Здесь используется более сложная палитра из восьми цветов, плавно переходящая от темно-синего через оттенки пламени к черному и серому. Важное отличие — отсутствие colorEase и scale.ease. Частицы не меняют размер плавно, а просто исчезают (scale: 0.75), что вместе с более темными цветами создает иллюзию плотного, клубящегося дыма.

const smokey = this.add.particles(650, 550, 'flares',
{
    frame: 'white',
    color: [ 0x040d61, 0xfacc22, 0xf89800, 0xf83600, 0x9f0404, 0x4b4a4f, 0x353438, 0x040404 ],
    lifespan: 1500,
    angle: { min: -100, max: -80 },
    scale: 0.75, // Постоянный размер, нет анимации масштаба
    speed: { min: 200, max: 300 },
    advance: 2000,
    blendMode: 'ADD'
});

Секреты настройки: Blend Mode и Advance

Два параметра критически важны для качественного эффекта.

* blendMode: 'ADD' (Режим наложения «Добавление»): Частицы не перекрывают друг друга, а их цвета складываются. Это создает эффект свечения и наложения, идеальный для огня, света и магии. Без этого параметра частицы будут выглядеть как непрозрачные круги. * advance: 2000: Этот параметр «проматывает» таймер жизни частицы вперед на 2000 мс при ее создании. Фактически, частица рождается уже в середине своего жизненного цикла. Это позволяет сразу получить полноценный эффект (например, яркое пламя), а не ждать, пока частица «разгорится» от нуля.

// Это ключевые параметры для «сочного» эффекта
blendMode: 'ADD',
advance: 2000

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

Используя всего один спрайт и мощный API this.add.particles, вы можете создавать десятки уникальных визуальных эффектов. Экспериментируйте: попробуйте менять порядок цветов в массиве color, комбинируйте разные кривые (ease) для scale и colorEase, изменяйте blendMode на NORMAL или MULTIPLY для других типов эффектов (например, дыма без свечения). Не бойтесь создавать эмиттеры, которые следуют за игровым персонажем, — это оживит вашу игру.