О чем этот пример
Эффекты частиц могут легко "уронить" производительность игры, если их не контролировать. В Phaser Particle Emitter есть встроенные инструменты для управления количеством частиц, которые позволяют создавать красивые эффекты, не перегружая процессор. В этой статье мы разберем ключевые свойства `maxAliveParticles` и `quantity`, которые помогут вам держать производительность под контролем.
Версия 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.spritesheet('fish', 'assets/sprites/fish-136x80.png', { frameWidth: 136, frameHeight: 80 });
}
create ()
{
const particles = this.add.particles('fish');
const emitter = particles.createEmitter({
frame: 1,
x: { min: 0, max: 800 },
y: 100,
gravityY: 200,
lifespan: { min: 1500, max: 3000 },
maxAliveParticles: 16,
quantity: 4
});
}
}
const config = {
type: Phaser.WEBGL,
width: 800,
height: 600,
backgroundColor: '#000',
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Зачем ограничивать частицы?
Система частиц (Particle Emitter) — мощный инструмент для создания эффектов дыма, огня, магии или роя насекомых. Однако, если эмиттер будет бесконечно создавать новые частицы, они быстро накопятся в памяти и начнут тормозить игру, особенно на мобильных устройствах.
К счастью, Phaser предоставляет простой способ установить лимиты. В примере используется спрайтшит с изображением рыбы, но принципы универсальны для любых частиц.
Давайте посмотрим на конфигурацию эмиттера из исходного кода.
Ключевые свойства: `maxAliveParticles` и `quantity`
В методе createEmitter передается объект конфигурации. Два свойства играют решающую роль в управлении "населением" частиц.
maxAliveParticles устанавливает жесткий лимит на общее количество частиц, которые могут существовать одновременно. Как только лимит достигнут, эмиттер перестанет создавать новые частицы, пока старые не "умрут".
quantity определяет, сколько частиц создается за один "выпуск". Часто эмиттер выпускает частицы не по одной, а пачками для более плотного эффекта.
Вот как выглядит конфигурация эмиттера из примера:
const emitter = particles.createEmitter({
frame: 1,
x: { min: 0, max: 800 },
y: 100,
gravityY: 200,
lifespan: { min: 1500, max: 3000 },
maxAliveParticles: 16,
quantity: 4
});
Здесь maxAliveParticles: 16 означает, что на экране никогда не будет больше 16 рыб одновременно. Свойство quantity: 4 указывает, что каждый раз эмиттер будет пытаться создать сразу 4 новые частицы.
Как это работает на практике?
Давайте проследим логику работы эмиттера с такими настройками.
1. **Старт:** Эмиттер создает первую партию из quantity (4) частиц.
2. **Цикл жизни:** У каждой частицы есть lifespan (время жизни от 1.5 до 3 секунд). По истечении этого времени частица автоматически уничтожается.
3. **Лимит:** Эмиттер продолжает создавать новые партии по 4 частицы, но строго следит за лимитом maxAliveParticles (16). Если на экране уже 16 частиц, создание новых приостанавливается.
4. **Освобождение ресурсов:** Как только одна или несколько частиц "умирают" (их время жизни истекло), счетчик живых частиц уменьшается. Эмиттер получает возможность создать новую партию, чтобы снова заполнить квоту до 16.
Таким образом, в системе постоянно поддерживается активный, но ограниченный пул из 16 частиц, что безопасно для производительности.
Обратите внимание на другие важные свойства в конфиге:
- frame: 1 — выбирает конкретный кадр из спрайтшита для частиц.
- x: { min: 0, max: 800 } — частицы будут появляться в случайной точке по горизонтали.
- gravityY: 200 — частицы будут падать вниз с ускорением.
Полная настройка сцены и игры выглядит стандартно:
const config = {
type: Phaser.WEBGL,
width: 800,
height: 600,
backgroundColor: '#000',
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Оптимизация и тонкая настройка
Сочетание maxAliveParticles и quantity позволяет гибко управлять видом эффекта.
- **Для редких, одиночных всплесков** (например, брызги воды) используйте quantity: 1 и небольшой maxAliveParticles (например, 5-10).
- **Для плотных, постоянных эффектов** (дым из трубы) установите quantity в значение, равное или кратное maxAliveParticles. Это создаст ощущение непрерывного потока.
- **Баланс производительности:** Всегда начинайте с консервативных значений. Увеличивайте maxAliveParticles только если эффект выглядит слишком разреженно, и обязательно тестируйте производительность на целевых платформах.
Важно помнить, что lifespan (время жизни) также влияет на заполнение лимита. Короткая жизнь частиц при высоком quantity может привести к очень частому обновлению пула, что тоже нагружает систему.
Инициализация системы частиц и эмиттера в Phaser всегда следует одной схеме:
// 1. Создаем менеджер частиц
const particles = this.add.particles('fish');
// 2. Создаем эмиттер с конфигурацией
const emitter = particles.createEmitter({ /* config */ });
Что попробовать дальше
Использование maxAliveParticles и quantity — это основа создания производительных и визуально приятных эффектов частиц в Phaser. Эти свойства являются вашей защитой от лагов и падения FPS.
**Идеи для экспериментов:**
1. Попробуйте создать эффект дождя с quantity: 50 и maxAliveParticles: 200, а затем резко уменьшите maxAliveParticles до 20. Обратите внимание, как изменится нагрузка и визуальная плотность.
2. Свяжите quantity со входными данными игрока (например, силой нажатия кнопки), чтобы количество создаваемых частиц реагировало на действия.
3. Создайте несколько эмиттеров с разными лимитами для одного сложного эффекта (например, огонь с искрами).
