О чем этот пример
При создании визуальных эффектов, таких как огонь, дым или магия, важно контролировать производительность. Неограниченный поток частиц может привести к падению 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 кадра при столкновении или взрыве для создания эффекта "всплеска", который затем возвращается к стабильному фоновому значению.
