О чем этот пример
Создание визуальных эффектов — ключевая часть гейм-дева. Частицы могут оживить окружение, придать удару вес или нарисовать след от магического заклинания. Часто нужно, чтобы частицы появлялись не просто в одной точке, а вдоль определённой линии или контура. В этой статье мы разберём, как использовать `addEmitZone` в Phaser для создания сложных и интересных паттернов эмиссии частиц, основанных на стандартных геометрических фигурах. Вы научитесь контролировать, откуда именно рождаются частицы, что сразу же повысит визуальную уникальность ваших эффектов.
Версия 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.image('bg', 'assets/skies/darkstone.png');
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 emitter = this.add.particles(400, 300, 'flares', {
frame: { frames: [ 'red', 'green', 'blue', 'white', 'yellow' ], cycle: true },
blendMode: 'ADD',
lifespan: 500,
quantity: 4,
scale: { start: 0.5, end: 0.1 }
});
emitter.addEmitZone({ type: 'edge', source: shape1, quantity: 64, total: 1 });
emitter.addEmitZone({ type: 'edge', source: shape2, quantity: 64, total: 1 });
emitter.addEmitZone({ type: 'edge', source: shape3, quantity: 64, total: 1 });
emitter.addEmitZone({ type: 'edge', source: shape4, quantity: 64, total: 1 });
emitter.addEmitZone({ type: 'edge', source: shape5, quantity: 64, total: 1 });
}
}
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
backgroundColor: '#000',
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Загрузка ресурсов и создание фигур
В методе preload загружается фон и атлас частиц. Атлас flares содержит несколько спрайтов разных цветов, которые мы будем использовать для эффекта.
Основная работа происходит в create. Первым делом мы создаём пять различных геометрических фигур, используя встроенные в Phaser классы геометрии. Важно отметить, что координаты для этих фигур задаются относительно их центра (точки 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);
Создание и настройка эмиттера частиц
Далее мы создаём сам эмиттер с помощью this.add.particles. Его начальная позиция задаётся координатами (400, 300) — это центр сцены. Эмиттер будет использовать текстуру flares.
Конфигурационный объект позволяет тонко настроить поведение частиц:
- frame: Задаёт кадры из атласа. Массив ['red', 'green', 'blue', 'white', 'yellow'] и флаг cycle: true означают, что частицы будут циклически появляться всех этих цветов по очереди.
- blendMode: 'ADD': Режим наложения, который делает яркие частицы ещё ярче, что идеально для эффектов вроде огня или вспышек.
- lifespan: 500: Время жизни частицы в миллисекундах.
- quantity: 4: Количество частиц, испускаемых за один выброс.
- scale: Позволяет частицам уменьшаться с 0.5 до 0.1 за время их жизни.
const emitter = this.add.particles(400, 300, 'flares', {
frame: { frames: [ 'red', 'green', 'blue', 'white', 'yellow' ], cycle: true },
blendMode: 'ADD',
lifespan: 500,
quantity: 4,
scale: { start: 0.5, end: 0.1 }
});
Добавление зон эмиссии с помощью addEmitZone
Самая важная часть — метод emitter.addEmitZone(). Он добавляет к эмиттеру зону, из которой будут появляться частицы. В нашем примере мы добавляем пять таких зон, по одной для каждой созданной ранее фигуры.
Параметры, передаваемые в метод, определяют поведение зоны:
- type: 'edge': Указывает, что частицы должны появляться вдоль границы (ребра) фигуры, а не внутри неё. Это создаёт эффект контура.
- source: Сама геометрическая фигура, которая служит источником для зоны.
- quantity: 64: Это общее количество точек, которые будут сгенерированы вдоль границы фигуры. Чем больше значение, тем более равномерным будет распределение частиц по контуру (например, для круга).
- total: 1: Количество частиц, которые будут испущены из этой зоны за один цикл. В нашем случае каждая зона испускает по одной частице за раз.
Эмиттер автоматически циклически перебирает все добавленные зоны, создавая частицы то из одной, то из другой.
emitter.addEmitZone({ type: 'edge', source: shape1, quantity: 64, total: 1 });
emitter.addEmitZone({ type: 'edge', source: shape2, quantity: 64, total: 1 });
emitter.addEmitZone({ type: 'edge', source: shape3, quantity: 64, total: 1 });
emitter.addEmitZone({ type: 'edge', source: shape4, quantity: 64, total: 1 });
emitter.addEmitZone({ type: 'edge', source: shape5, quantity: 64, total: 1 });
Что попробовать дальше
Использование addEmitZone открывает огромные возможности для создания нестандартных визуальных эффектов. Вместо статичного облака частиц вы получаете динамичные узоры, очерчивающие любую геометрическую форму. Для экспериментов попробуйте:
1. Изменить type на 'random', чтобы частицы появлялись в случайной точке *внутри* фигуры.
2. Поиграть с параметром total, заставляя зону испускать несколько частиц одновременно.
3. Создать свою сложную фигуру с помощью Phaser.Geom.Polygon и использовать её как источник.
4. Динамически менять source зоны в runtime, чтобы форма эффекта плавно трансформировалась.
