О чем этот пример
При создании сложных визуальных эффектов с помощью системы частиц Phaser порядок их отрисовки может критично влиять на итоговый вид сцены. По умолчанию, частицы эмиттера рисуются в том порядке, в котором они создаются, что может привести к ситуации, когда новые частицы оказываются под старыми. В этой статье мы разберем, как управлять этим порядком с помощью свойства `particleBringToTop`, чтобы ваши эффекты всегда выглядеть так, как вы задумали. Это особенно полезно для эффектов огня, дыма, магии или любых других, где новые частицы должны быть поверх старых для создания иллюзии объема.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.atlas('blocks', 'assets/sprites/blocks.png', 'assets/sprites/blocks.json');
}
create ()
{
const emitter = this.add.particles(100, 300, 'blocks', {
frame: 'redmonster',
lifespan: 5000,
angle: { min: -30, max: 30 },
speed: 150,
frequency: 200
});
const text = this.add.text(10, 10, 'Click to change. bringToTop: true');
this.input.on('pointerdown', () => {
if (emitter.particleBringToTop)
{
emitter.particleBringToTop = false;
}
else
{
emitter.particleBringToTop = true;
}
text.setText(`Click to change. bringToTop: ${emitter.particleBringToTop}`);
});
}
}
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
backgroundColor: '#000',
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Понимание базового примера
В представленном примере создается сцена с эмиттером частиц и текстовой подсказкой. Основная логика заключается в переключении режима отрисовки частиц по клику мыши.
Давайте разберем ключевые части кода. В методе create() создается сам эмиттер. Конфигурация частиц задает их внешний вид и поведение.
const emitter = this.add.particles(100, 300, 'blocks', {
frame: 'redmonster',
lifespan: 5000,
angle: { min: -30, max: 30 },
speed: 150,
frequency: 200
});
Эмиттер создается в точке (100, 300) с использованием атласа blocks. Частицы используют спрайт redmonster, живут 5 секунд, вылетают под случайным углом от -30 до 30 градусов со скоростью 150 пикселей в секунду и появляются каждые 200 миллисекунд.
Свойство particleBringToTop эмиттера изначально не установлено явно, поэтому используется поведение по умолчанию.
Свойство particleBringToTop и его роль
Свойство particleBringToTop объекта эмиттера (ParticleEmitter) контролирует, куда будет добавлена новая частица в списке отрисовки своего родительского контейнера.
- Если particleBringToTop равно true, каждая вновь созданная частица будет помещена в конец списка отрисовки контейнера. При отрисовке это означает, что новые частицы будут рисоваться поверх всех ранее созданных частиц этого эмиттера.
- Если particleBringToTop равно false (значение по умолчанию), частицы добавляются в порядке создания. Это может привести к тому, что старые частицы, которые еще не "умерли", будут перекрывать новые, если система отрисовки не сортирует их по глубине (например, по координате Y).
Визуально это выглядит так: при true фонтан частиц будет выглядеть как четкий поток, где новые элементы сверху. При false поток может казаться более "плоским" или хаотичным, так как новые частицы могут оказаться под старыми.
Интерактивное переключение режима
В примере добавлен обработчик клика, который позволяет в реальном времени увидеть разницу между двумя режимами.
Сначала создается текст для отображения текущего состояния.
const text = this.add.text(10, 10, 'Click to change. bringToTop: true');
Затем на событие pointerdown вешается обработчик. Его логика проста: инвертировать текущее значение particleBringToTop и обновить текст.
this.input.on('pointerdown', () => {
if (emitter.particleBringToTop)
{
emitter.particleBringToTop = false;
}
else
{
emitter.particleBringToTop = true;
}
text.setText(`Click to change. bringToTop: ${emitter.particleBringToTop}`);
});
Обратите внимание: в исходном коде текст инициализирован строкой 'bringToTop: true', хотя свойство явно не установлено. В Phaser 3 значение по умолчанию для particleBringToTop — false. Поэтому при первом клике оно станет true, и текст обновится на корректное значение. Это небольшая неточность в исходном примере, но она не мешает демонстрации принципа.
Практическое применение и нюансы
Использование particleBringToTop — это локальное решение для одного эмиттера. Оно влияет только на порядок частиц внутри их собственного контейнера (ParticleEmitter является GameObject).
Важно понимать, что это свойство не влияет на порядок отрисовки самого эмиттера относительно других игровых объектов на сцене. Глубиной (z-index) эмиттера как целого управляют стандартными методами, например, this.children.bringToTop(emitter).
// Чтобы поднять весь эмиттер (со всеми его частицами) поверх других объектов:
this.children.bringToTop(emitter);
Свойство particleBringToTop идеально подходит для эффектов, которые должны имитировать источник, испускающий элементы наружу, такие как искры, брызги воды или струя пара. Для эффектов, которые должны оседать или опускаться (например, падающие листья), значение false может выглядеть более естественно.
Что попробовать дальше
Свойство particleBringToTop — это простой, но мощный инструмент для тонкой настройки визуальной иерархии внутри системы частиц. Поэкспериментируйте, создавая разные эффекты: попробуйте для одного эмиттера false, а для другого — true, и разместите их на разных слоях сцены. Интересный эксперимент — создать эмиттер с очень большим lifespan и, кликая, переключать свойство, наблюдая, как меняется визуальная структура уже выпущенных и новых частиц. Это поможет лучше понять, как Phaser управляет отрисовкой и как создавать по-настоящему красивые и контролируемые визуальные эффекты.
