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

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

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

    create ()
    {
        const path = new Phaser.Curves.Path(400, 300).circleTo(100).moveTo(400, 300).circleTo(100, true, 180);

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

        particles.createEmitter({
            frame: { frames: [ 'red', 'green', 'blue' ], cycle: true },
            scale: { start: 0.5, end: 0 },
            blendMode: 'ADD',
            emitZone: { type: 'edge', source: path, quantity: 48, yoyo: false }
        });
    }
}

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

const game = new Phaser.Game(config);

Подготовка: загрузка атласа частиц

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

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

Метод this.load.setBaseURL() задает базовый URL для всех последующих загрузок. Метод this.load.atlas() загружает изображение flares.png и файл данных flares.json, который описывает, где находятся отдельные кадры (например, 'red', 'green', 'blue') внутри этого изображения.

Создание кривой-пути для движения частиц

В Phaser 3 класс Phaser.Curves.Path позволяет создавать сложные составные пути из различных типов кривых. Частицы будут появляться вдоль этого пути.

const path = new Phaser.Curves.Path(400, 300).circleTo(100).moveTo(400, 300).circleTo(100, true, 180);

Разберем эту цепочку вызовов по порядку: 1. new Phaser.Curves.Path(400, 300) — создает объект пути, начиная его в точке с координатами x:400, y:300 (центр экрана при разрешении 800x600). 2. .circleTo(100) — добавляет к пути полную окружность радиусом 100 пикселей. 3. .moveTo(400, 300) — возвращает «перо» пути обратно в исходную центральную точку, не рисуя при этом линию. 4. .circleTo(100, true, 180) — добавляет вторую окружность. Параметры true и 180 указывают, что окружность должна рисоваться по часовой стрелке (clockwise: true) и ее угол составит 180 градусов, то есть это будет полукруг.

В результате получается фигура, похожая на цифру «8» или знак бесконечности.

Настройка менеджера и эмиттера частиц

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

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

Затем в этом менеджере создается эмиттер — объект, который непосредственно генерирует, обновляет и управляет частицами.

particles.createEmitter({
    frame: { frames: [ 'red', 'green', 'blue' ], cycle: true },
    scale: { start: 0.5, end: 0 },
    blendMode: 'ADD',
    emitZone: { type: 'edge', source: path, quantity: 48, yoyo: false }
});

Конфигурация эмиттера: - frame: Определяет, какие кадры из атласа будут использоваться. Массив ['red', 'green', 'blue'] и флаг cycle: true заставляют частицы циклически менять свой цвет с красного на зеленый, затем на синий. - scale: Задает изменение размера частицы за время ее жизни от 0.5 до `0` (полное исчезновение). - blendMode: 'ADD' — режим наложения, при котором цвета частиц складываются, создавая яркие, светящиеся эффекты. - emitZone — ключевой параметр. Его тип 'edge' означает, что частицы будут появляться равномерно вдоль всей границы (края) заданного источника (source: path). Параметр quantity: 48 определяет общее количество точек эмиссии вдоль этого пути, то есть одновременно по фигуре будет распределено 48 частиц.

Конфигурация и запуск игры

Сцена готова, осталось создать экземпляр игры с базовой конфигурацией.

const config = {
    type: Phaser.WEBGL, // Использование WebGL для лучшей производительности и поддержки blendMode 'ADD'
    width: 800,
    height: 600,
    backgroundColor: '#000', // Черный фон для контраста со светящимися частицами
    parent: 'phaser-example', // ID HTML-элемента, в который будет встроен canvas
    scene: Example // Класс основной сцены
};

const game = new Phaser.Game(config);

Важно использовать type: Phaser.WEBGL, так как режим наложения 'ADD' для частиц корректно работает только в WebGL-рендерере.

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

Использование путей в качестве зоны эмиссии — это простой, но невероятно мощный прием для создания структурированных и красивых эффектов частиц. Вы можете заменить circleTo на lineTo, splineThrough или ellipseTo для создания траекторий любой сложности: волн, спиралей, орбит планет или паттернов заклинаний. **Идеи для экспериментов:** 1. Измените параметр quantity в emitZone, чтобы увидеть, как количество точек эмиссии влияет на плотность эффекта. 2. Попробуйте использовать emitZone с типом 'random' вместо 'edge', передав ему тот же путь в качестве source. Частицы будут появляться в случайных точках внутри площади, ограниченной этой фигурой. 3. Анимируйте саму кривую path с помощью getPoint и tween, чтобы создать движущийся источник частиц, например, след за двигающимся кораблем.