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

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

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

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

        let customAngle = 0;

        this.input.on('pointerup', () =>
        {

            customAngle += 90;

        });

        const emitter = particles.createEmitter({
            x: 400,
            y: 300,
            speed: 180,
            lifespan: 3000,
            rotate: { onEmit: function () { return customAngle; } }
        });

        const text = this.add.text(10, 10, 'Click to change particle angle', { font: '16px Courier', fill: '#ffffff' });
    }
}

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

const game = new Phaser.Game(config);

Суть примера: Динамический угол поворота

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

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

Разбор кода: От события к изменению частицы

Давайте пройдемся по ключевым моментам реализации.

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

const particles = this.add.particles('arrow');
let customAngle = 0;

Затем на событие клика (pointerup) мы навешиваем обработчик, который меняет значение этой переменной.

this.input.on('pointerup', () => {
    customAngle += 90;
});

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

const emitter = particles.createEmitter({
    x: 400,
    y: 300,
    speed: 180,
    lifespan: 3000,
    rotate: { onEmit: function () { return customAngle; } }
});

Таким образом, все частицы, созданные после клика, будут иметь новый угол (90, 180, 270 градусов и т.д.), в то время как ранее выпущенные частицы сохранят свой исходный угол.

Где это можно использовать?

Такой подход не ограничивается только углом поворота (rotate). Функции onEmit доступны для целого ряда свойств частиц в Phaser 3, открывая огромные возможности для кастомизации:

* speed: Скорость частицы может зависеть от силы удара или заряда способности. * scale: Размер частицы может уменьшаться со временем или увеличиваться от уровня персонажа. * alpha (прозрачность): Можно создавать эффекты постепенного появления или исчезновения. * tint: Цвет частицы может меняться в зависимости от элемента урона (огонь, лед, яд).

Ключевая идея в том, что функция onEmit имеет доступ к текущему контексту игры. Вы можете читать состояние любых объектов, переменных или систем (например, this.player.chargePower) и на основе этого вычислять свойства частицы.

Важный нюанс: Функция против значения

Обратите внимание на синтаксис. Чтобы свойство использовало функцию, его нужно передать как объект с полем onEmit.

**Так работает динамически:**

rotate: { onEmit: function () { return customAngle; } }
// или через стрелочную функцию:
// rotate: { onEmit: () => customAngle }

**А так — статически (все частицы будут под углом 45 градусов):**

rotate: 45

Не забудьте этот синтаксис, иначе функция не будет вызвана, и вы получите неожиданный результат или ошибку.

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

Использование onEmit — это мощный шаг от предопределенных эффектов к по-настоящему интерактивной системе частиц. Ваши визуальные эффекты теперь могут "чувствовать" игру и реагировать на нее. **Идеи для экспериментов:** 1. Свяжите угол разлета частиц (angle) с направлением движения персонажа. 2. Заставьте цвет частиц (tint) плавно меняться, вычисляя его внутри onEmit на основе синуса от времени игры (this.time.now). 3. Создайте эмиттер, где скорость частицы зависит от расстояния до курсора мыши в момент ее создания.