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

Частицы — это простой способ добавить в игру динамичные визуальные эффекты: огонь, дым, магию или звёздную пыль. В 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.image('spark', 'assets/particles/blue.png');
    }

    create ()
    {
        const particles = this.add.particles('spark');

        const emitter = particles.createEmitter({
            x: 600,
            y: 100,
            angle: { min: 140, max: 180 },
            speed: 400,
            gravityY: 200,
            lifespan: { min: 1000, max: 2000 },
            blendMode: 'ADD'
        });
    }
}

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

const game = new Phaser.Game(config);

Основа: создание менеджера частиц

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

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

Здесь this.add.particles('spark') создаёт менеджер для текстуры с ключом 'spark'. Ключ должен соответствовать изображению, загруженному в preload. Сам по себе менеджер не испускает частицы — для этого нужен эмиттер.

Конфигурация эмиттера: объект параметров

Эмиттер создаётся вызовом метода .createEmitter() у менеджера частиц. Вся его логика задаётся через конфигурационный объект. Давайте разберём параметры из примера.

const emitter = particles.createEmitter({
    x: 600,
    y: 100,
    angle: { min: 140, max: 180 },
    speed: 400,
    gravityY: 200,
    lifespan: { min: 1000, max: 2000 },
    blendMode: 'ADD'
});
*   `x`, `y`: координаты точки испускания частиц.
*   `angle`: направление движения. Объект `{ min: 140, max: 180 }` означает, что каждая частица получит случайный угол в этом диапазоне (в градусах). Угол 0 — движение вправо.
*   `speed`: начальная скорость частицы в пикселях в секунду.
*   `gravityY`: сила гравитации, приложенная по оси Y. Положительное значение тянет частицы вниз.
*   `lifespan`: время жизни частицы в миллисекундах. Частица исчезнет по его истечении. Задание диапазона `{ min: 1000, max: 2000 }` делает исчезновение более естественным.
*   `blendMode`: режим наложения. `'ADD'` делает частицы яркими и светящимися, что идеально для огня или энергии.

Как это работает вместе: физика частиц

При создании эмиттер немедленно начинает испускать частицы с заданной точки. Движение каждой частицы рассчитывается на основе переданных физических параметров.

1. Частица появляется в точке (600, 100). 2. Ей присваивается случайный угол между 140° и 180° (примерно направление влево и вверх). 3. Она летит с высокой скоростью (400 px/sec) по этому направлению. 4. На неё действует гравитация (gravityY: 200), которая постепенно отклоняет траекторию вниз. 5. Через 1-2 секунды частица автоматически уничтожается.

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

// Это поведение создаёт параболические траектории
speed: 400,
gravityY: 200

Почему конфиг — это удобно

Использование конфигурационного объекта вместо цепочки вызовов методов (setAngle, setSpeed и т.д.) имеет ключевые преимущества.

* **Наглядность**: Все параметры эмиттера видны в одном месте. * **Безопасность**: Опечатка в имени свойства вызовет ошибку, тогда как опечатка в названии метода может создать молчаливый баг. * **Гибкость**: Конфиг легко сериализовать (сохранить в JSON), что полезно для редакторов уровней или загрузки эффектов из данных.

Вы можете вынести конфиг в отдельную константу или даже загрузить его с сервера.

const smokeConfig = {
    x: 400,
    y: 300,
    speed: 50,
    scale: { start: 1, end: 0 },
    lifespan: 3000
};
const smokeEmitter = particles.createEmitter(smokeConfig);

Управление эмиттером в реальном времени

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

emitter.on = false; // Останавливает генерацию новых частиц

Или чтобы переместить источник частиц за игровым персонажем.

// В методе update() сцены
emitter.setPosition(player.x, player.y);

Это позволяет создавать динамические эффекты, такие как след от двигателя или дым из-под повреждённой машины.

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

Создание эмиттера частиц из конфигурационного объекта в Phaser — это мощный и декларативный способ добавления сложных визуальных эффектов. Вы детально контролируете рождение, движение и исчезновение каждой частицы. **Идеи для экспериментов:** 1. Измените blendMode на 'SCREEN' или 'MULTIPLY' и посмотрите, как это повлияет на цветовое смешение. 2. Добавьте параметр scale, чтобы частицы увеличивались или уменьшались со временем: scale: { start: 0.5, end: 2 }. 3. Сделайте эмиттер следящим, привязав его координаты `xиyк положению курсора мыши в событииpointermove`. 4. Создайте несколько эмиттеров с разными конфигами из одной текстуры для составного эффекта (например, ядро огня и разлетающиеся искры).