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

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

Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.55.2.

Живой запуск

Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.

Исходный код


class Example extends Phaser.Scene
{
    particles;
    fpsText;

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

    create ()
    {
        this.fpsText = this.add.text(10, 10, 'FPS: -- \n-- Particles', {
            font: 'bold 26px Arial',
            fill: '#ffffff'
        });

        this.particles = this.add.particles('fire');

        this.particles.createEmitter({
            alpha: { start: 1, end: 0 },
            scale: { start: 0.5, end: 2.5 },

            // tint: { start: 0xff945e, end: 0xff945e },
            speed: 20,
            accelerationY: -300,
            angle: { min: -85, max: -95 },
            rotate: { min: -180, max: 180 },
            lifespan: { min: 1000, max: 1100 },
            blendMode: 'ADD',
            frequency: 110,
            maxParticles: 10,
            x: 400,
            y: 300
        });
    }

    update (time, delta)
    {
        this.fpsText.setText(`FPS: ${(1000 / delta).toFixed(3)}\n${this.particles.emitters.first.alive.length} Particles`);
    }
}

/**
 * @author    Pavle Goloskokovic <pgoloskokovic@gmail.com> (http://prunegames.com)
 */

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

const game = new Phaser.Game(config);

Настройка эмиттера с лимитом

Ключевой параметр, ограничивающий количество частиц, — maxParticles. В данном примере он установлен в 10.

maxParticles: 10

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

Конфигурация эффекта пламени

Эмиттер настроен для имитации вспышек пламени. Давайте разберём основные параметры:

this.particles.createEmitter({
    alpha: { start: 1, end: 0 },
    scale: { start: 0.5, end: 2.5 },
    speed: 20,
    accelerationY: -300,
    angle: { min: -85, max: -95 },
    rotate: { min: -180, max: 180 },
    lifespan: { min: 1000, max: 1100 },
    blendMode: 'ADD',
    frequency: 110,
    maxParticles: 10,
    x: 400,
    y: 300
});

* alpha и scale: Частицы рождаются видимыми (alpha: 1) и маленькими (scale: 0.5), а затем постепенно увеличиваются и исчезают. * speed и accelerationY: Начальная скорость 20 пикселей в секунду и сильное отрицательное ускорение по оси Y (-300) заставляют частицы резко взлетать вверх и замедляться, как настоящее пламя. * angle: Частицы испускаются в узком конусе, направленном вверх (углы от -85 до -95 градусов). * lifespan: Время жизни от 1 до 1.1 секунды. * blendMode: 'ADD': Этот режим наложения делает яркие области эффекта ещё ярче, что идеально для огня и свечения. * frequency: Новая частица будет пытаться появиться каждые 110 миллисекунд, но только если количество активных частиц меньше maxParticles.

Мониторинг производительности в реальном времени

Класс Example содержит метод update, который обновляет текстовое поле для отображения текущего FPS и количества активных частиц.

update (time, delta)
{
    this.fpsText.setText(`FPS: ${(1000 / delta).toFixed(3)}\n${this.particles.emitters.first.alive.length} Particles`);
}

* (1000 / delta).toFixed(3): Рассчитывает FPS на основе времени delta, прошедшего с предыдущего кадра (в миллисекундах). * this.particles.emitters.first.alive.length: Обращается к списку alive первого эмиттера в системе частиц (this.particles) и получает его текущую длину. Это и есть количество активных частиц, которое никогда не превысит 10 благодаря параметру maxParticles. Этот мониторинг наглядно демонстрирует, как лимит стабилизирует производительность.

Практические советы по использованию

1. **Для фоновых эффектов**: Установите maxParticles на минимально необходимое значение для достижения нужного визуального впечатления. Например, для далёкого костра может хватить 5-7 частиц. 2. **Баланс частоты и лимита**: Параметр frequency определяет, как часто эмиттер *пытается* создать частицу. Если frequency очень низкая (например, 500 мс), а maxParticles высокий (50), лимит может никогда не быть достигнут. Настройте эти значения в паре. 3. **Отладка**: Всегда используйте подобный текстовый вывод для отслеживания количества частиц в сложных сценах, особенно при использовании нескольких эмиттеров. Это поможет найти "прожорливые" эффекты. 4. **Динамическое изменение**: Значение maxParticles можно менять в runtime через свойство эмиттера. Например, чтобы усилить эффект, когда игрок приближается к объекту.

this.emitter.setMaxParticles(20);

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

Использование maxParticles — это простой и эффективный способ контролировать производительность системы частиц в Phaser. Он позволяет создавать выразительные эффекты, не беспокоясь о падении частоты кадров. **Идеи для экспериментов:** 1. Создайте несколько эмиттеров с разными текстурами (искры, дым) в одной точке, каждый со своим небольшим лимитом, чтобы получить сложный составной эффект. 2. Свяжите значение maxParticles со здоровьем игрока или уровнем маны, чтобы визуализировать эти характеристики. 3. Поэкспериментируйте с резким увеличением maxParticles на 1-2 кадра при столкновении или взрыве для создания эффекта "всплеска", который затем возвращается к стабильному фоновому значению.