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

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

Версия 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 particles = this.add.particles('flares');

        const circle = new Phaser.Geom.Circle(400, 300, 530);

        const emitter = particles.createEmitter({
            frame: { frames: [ 'red', 'green', 'blue' ], cycle: true, quantity: 32 * 4 },
            x: 0,
            y: 0,
            moveToX: 400,
            moveToY: 300,
            lifespan: 1000,
            quantity: 4,
            scale: { start: 0.8, end: 0.2 },
            delay: 1000,
            blendMode: 'ADD',
            emitZone: { source: circle, type: 'edge', quantity: 32 }
        });

        console.log(emitter);
    }
}

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

const game = new Phaser.Game(config);

Подготовка сцены и загрузка атласа

Вся работа начинается в методе preload(). Здесь мы загружаем необходимый для частиц ресурс — атлас. Атлас 'flares' содержит несколько спрайтов частиц разного цвета в одном изображении и JSON-файл с данными о их расположении.

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

Первая строка задает базовый URL для загрузки, что позволяет использовать относительные пути. Далее метод this.load.atlas() загружает сам атлас, передавая ему ключ 'flares', путь к изображению и путь к файлу с данными.

Создание менеджера частиц и геометрии

В методе create() мы создаем систему для работы с частицами и определяем зону, из которой они будут появляться.

const particles = this.add.particles('flares');
const circle = new Phaser.Geom.Circle(400, 300, 530);

Строка this.add.particles('flares') создает менеджер частиц (ParticleEmitterManager), который будет использовать загруженный атлас 'flares'. Это фабрика для эмиттеров.

Далее мы создаем геометрический объект — круг (Phaser.Geom.Circle). Его центр находится в точке (400, 300), а радиус равен 530. Этот круг не отрисовывается на экране, он служит исключительно источником данных для зоны эмиссии.

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

Самый важный шаг — создание и конфигурация эмиттера. Именно здесь задается поведение частиц.

const emitter = particles.createEmitter({
    frame: { frames: [ 'red', 'green', 'blue' ], cycle: true, quantity: 32 * 4 },
    x: 0,
    y: 0,
    moveToX: 400,
    moveToY: 300,
    lifespan: 1000,
    quantity: 4,
    scale: { start: 0.8, end: 0.2 },
    delay: 1000,
    blendMode: 'ADD',
    emitZone: { source: circle, type: 'edge', quantity: 32 }
});

Давайте разберем ключевые параметры: * frame: Частицы будут брать кадры 'red', 'green', 'blue' из атласа, циклически переключаясь между ними. Параметр quantity внутри frame определяет, сколько частиц будет создано для каждого кадра за один цикл. * `x,y: Начальные координаты эмиттера (0, 0). Но так как используетсяemitZone`, эти координаты игнорируются для позиции рождения частиц. * moveToX, moveToY: Это главная "фишка" примера. Частицы после рождения будут двигаться **к** указанной точке — центру круга (400, 300). * lifespan: Время жизни частицы в миллисекундах (1000 мс = 1 секунда). * quantity: Количество частиц, испускаемых за один выброс. * scale: Частица плавно уменьшается от размера 0.8 до 0.2 за время жизни. * delay: Пауза в 1000 мс между выбросами частиц. * blendMode: 'ADD' — режим наложения, который делает яркие цвета еще ярче, создавая эффект свечения. * emitZone: Зона эмиссии. source: circle — использует созданный круг. type: 'edge' — частицы будут рождаться строго на границе (ребре) этого круга. quantity: 32 — определяет, сколько точек на границе круга будет использоваться для расчета позиций рождения.

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

Финальный шаг — стандартная конфигурация объекта игры Phaser.Game и его создание.

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

В конфиге мы указываем использование WEBGL-рендерера для лучшей производительности и поддержки эффектов вроде blendMode: 'ADD'. Задаем черный фон ('#000') и указываем, что наша сцена Example будет запущена первой. После создания экземпляра Phaser.Game с этой конфигурацией игра запускается.

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

Мы разобрали, как создать эффект "притяжения" частиц из периферии в заданную точку, используя связку emitZone с геометрией Circle и параметры moveToX/moveToY. Этот базовый паттерн открывает множество возможностей. Попробуйте заменить Circle на Rectangle или Line, изменить type в emitZone на 'random', чтобы частицы рождались по всей площади фигуры, или анимировать целевые координаты moveToX/moveToY с помощью таймера или курсора мыши, чтобы создать интерактивный вихрь.