О чем этот пример
Создание визуально сложных эффектов частиц часто требует выхода за рамки простых точек испускания. В Phaser 3 система Particle Emitter предоставляет мощный инструмент `EmitZone`, который позволяет генерировать частицы не из одной координаты, а вдоль края любой геометрической фигуры. Эта техника полезна для создания эффектов ореолов, силовых полей, контурных взрывов или динамических границ объектов. В этой статье мы разберем пример, где один эмиттер может мгновенно переключаться между разными геометрическими зонами испускания по клику мыши, что открывает широкие возможности для интерактивной и динамической визуализации.
Версия 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.atlas('flares', 'assets/particles/flares.png', 'assets/particles/flares.json');
}
create ()
{
const shape1 = new Phaser.Geom.Circle(0, 0, 160);
const shape2 = new Phaser.Geom.Ellipse(0, 0, 500, 150);
const shape3 = new Phaser.Geom.Rectangle(-150, -150, 300, 300);
const shape4 = new Phaser.Geom.Line(-150, -150, 150, 150);
const shape5 = new Phaser.Geom.Triangle.BuildEquilateral(0, -140, 300);
const shapes = [ shape1, shape2, shape3, shape4, shape5 ];
let i = 0;
const particles = this.add.particles('flares');
const emitter = particles.createEmitter({
frame: { frames: [ 'red', 'green', 'blue' ], cycle: true },
x: 400,
y: 300,
scale: { start: 0.5, end: 0 },
blendMode: 'ADD',
emitZone: { type: 'edge', source: shape1, quantity: 48, yoyo: false }
});
this.input.on('pointerdown', pointer =>
{
i++;
if (i === shapes.length)
{
i = 0;
}
emitter.setEmitZone({ type: 'edge', source: shapes[i], quantity: 48, yoyo: false });
});
}
}
const config = {
type: Phaser.WEBGL,
width: 800,
height: 600,
backgroundColor: '#000',
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Подготовка сцены и загрузка атласа частиц
В методе preload() мы загружаем необходимый ресурс — атлас частиц. Атлас flares содержит несколько спрайтов разного цвета (кадры) в одном изображении, что эффективно для работы с частицами.
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.atlas('flares', 'assets/particles/flares.png', 'assets/particles/flares.json');
Создание набора геометрических фигур
В начале create() определяется массив различных геометрических объектов Phaser. Эти фигуры будут использоваться как источники (source) для зоны испускания. Каждая фигура создается с центром в точке (0, 0), что упрощает их последующее позиционирование относительно эмиттера.
const shape1 = new Phaser.Geom.Circle(0, 0, 160);
const shape2 = new Phaser.Geom.Ellipse(0, 0, 500, 150);
const shape3 = new Phaser.Geom.Rectangle(-150, -150, 300, 300);
const shape4 = new Phaser.Geom.Line(-150, -150, 150, 150);
const shape5 = new Phaser.Geom.Triangle.BuildEquilateral(0, -140, 300);
const shapes = [ shape1, shape2, shape3, shape4, shape5 ];
Инициализация менеджера частиц и эмиттера
Сначала создается менеджер частиц (ParticleManager), который отвечает за рендеринг всех связанных с ним эмиттеров. Затем в этом менеджере создается эмиттер — объект, который непосредственно испускает, обновляет и уничтожает частицы.
Ключевой параметр конфигурации — emitZone. Указав type: 'edge', мы говорим системе, что частицы должны появляться на краю фигуры-источника (source). Параметр quantity определяет, сколько точек вдоль края будет использовано для испускания частиц за один выброс.
const particles = this.add.particles('flares');
const emitter = particles.createEmitter({
frame: { frames: [ 'red', 'green', 'blue' ], cycle: true },
x: 400,
y: 300,
scale: { start: 0.5, end: 0 },
blendMode: 'ADD',
emitZone: { type: 'edge', source: shape1, quantity: 48, yoyo: false }
});
Динамическая смена зоны испускания
Для интерактивности добавляется обработчик клика мыши (pointerdown). При каждом клике индекс `iувеличивается, и эмиттеру назначается новая зона испускания с помощью методаsetEmitZone()`. Этот метод принимает тот же объект конфигурации, что и при создании, и мгновенно применяет изменения.
Таким образом, частицы начинают испускаться по контуру новой фигуры без перезапуска или создания нового эмиттера.
this.input.on('pointerdown', pointer => {
i++;
if (i === shapes.length) {
i = 0;
}
emitter.setEmitZone({ type: 'edge', source: shapes[i], quantity: 48, yoyo: false });
});
Конфигурация игры и запуск
Стандартная конфигурация игры Phaser. Обратите внимание на type: Phaser.WEBGL — для корректной работы blend mode 'ADD' необходим WebGL-рендерер.
const config = {
type: Phaser.WEBGL,
width: 800,
height: 600,
backgroundColor: '#000',
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Что попробовать дальше
Использование EmitZone типа edge — это мощный способ добавить геометрическую точность и разнообразие в ваши системы частиц. Вы можете использовать не только примитивные фигуры, но и собственные полигоны или пути.
**Идеи для экспериментов:**
1. Попробуйте анимировать саму фигуру-источник (например, вращать Phaser.Geom.Rectangle), частицы будут следовать за её контуром в реальном времени.
2. Скомбинируйте несколько эмиттеров с разными фигурами и настройками цвета, чтобы создать сложный составной эффект (например, магический круг).
3. Используйте quantity для управления плотностью частиц по краю и yoyo для изменения направления их генерации.
