О чем этот пример
Эмиттеры частиц в Phaser могут превратить статичные эффекты в динамичные визуальные системы. Встроенный компонент `EdgeZone` позволяет задавать точную геометрию для испускания частиц, но настоящая мощь раскрывается при использовании пользовательских источников. Эта статья покажет, как создавать собственные математические формы для эмиттеров и динамически изменять их в реальном времени, открывая путь к уникальным эффектам, таким как анимированные ауры, волшебные следы и сложные геометрические паттерны.
Версия 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 particles = this.add.particles('flares');
let k = 3;
const rose = {
getPoints: function (quantity, stepRate)
{
if (!stepRate)
{
stepRate = Phaser.Math.PI2 / quantity;
}
const input = Phaser.Utils.Array.NumberArrayStep(0, Phaser.Math.PI2, stepRate);
const output = new Array(input.length);
for (let i = 0; i < input.length; i++)
{
const angle = input[i];
output[i] = new Phaser.Math.Vector2().setToPolar(angle, 200 * Math.cos(k * angle));
}
return output;
}
};
const emitter = particles.createEmitter({
frame: { frames: [ 'green', 'blue' ], cycle: true },
x: 400,
y: 300,
scale: { start: 0.5, end: 0 },
blendMode: 'ADD',
emitZone: { type: 'edge', source: rose, quantity: 360 }
});
this.input.on('pointerup', () =>
{
k++;
emitter.emitZone.updateSource();
});
}
}
const config = {
type: Phaser.WEBGL,
width: 800,
height: 600,
backgroundColor: '#000',
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Основа: EdgeZone и пользовательский источник
В Phaser для создания эмиттера частиц используется this.add.particles(). Ключевую роль в позиционировании частиц играет конфигурация emitZone. При указании type: 'edge' мы говорим системе, что частицы будут появляться вдоль линии или кривой.
Параметр source определяет форму этой кривой. Это может быть встроенный объект геометрии Phaser (например, круг или прямоугольник) или пользовательский объект с обязательным методом getPoints(quantity, stepRate). Этот метод должен возвращать массив объектов Phaser.Math.Vector2, определяющих точки для испускания частиц.
emitZone: {
type: 'edge',
source: customShapeObject,
quantity: 360
}
Математика формы: полярные координаты и "розы"
В примере создается фигура, известная как "роза" или полярная роза. Её форма задается полярным уравнением: радиус зависит от угла.
Метод getPoints пользовательского объекта rose делает следующее:
1. Создает массив углов от 0 до 2π (полный круг) с заданным шагом stepRate.
2. Для каждого угла вычисляет радиус по формуле r = 200 * Math.cos(k * angle). Параметр `k` определяет количество "лепестков".
3. Преобразует полярные координаты (угол, радиус) в декартовы (x, y) с помощью Phaser.Math.Vector2().setToPolar().
const rose = {
getPoints: function (quantity, stepRate) {
// ... создание массива углов (input) ...
const output = new Array(input.length);
for (let i = 0; i < input.length; i++) {
const angle = input[i];
// Формула полярной розы
output[i] = new Phaser.Math.Vector2().setToPolar(angle, 200 * Math.cos(k * angle));
}
return output;
}
};
Сборка эмиттера: настройка визуала
Эмиттер конфигурируется с нашим пользовательским источником rose. Частицы берутся из атласа 'flares', и для создания цветового разнообразия используется анимация кадров frame. Частицы уменьшаются от размера 0.5 до 0 (scale) и используют аддитивное смешивание (blendMode: 'ADD'), что делает их яркими и подходящими для световых эффектов.
const emitter = particles.createEmitter({
frame: { frames: [ 'green', 'blue' ], cycle: true },
x: 400,
y: 300,
scale: { start: 0.5, end: 0 },
blendMode: 'ADD',
emitZone: { type: 'edge', source: rose, quantity: 360 }
});
Интерактивность: Обновление геометрии на лету
Самая интересная часть — динамическое изменение формы. По клику мыши увеличивается параметр `kв формуле розы. Чтобы эмиттер начал испускать частицы по новой форме, необходимо вызвать методemitZone.updateSource()`. Этот метод заставляет эмиттер пересчитать все точки источника заново. Новые частицы будут появляться уже на обновленной кривой, создавая живую, реагирующую на действия игрока анимацию.
this.input.on('pointerup', () => {
k++; // Меняем форму
emitter.emitZone.updateSource(); // Применяем изменения
});
Что попробовать дальше
Использование пользовательских источников для EdgeZone превращает эмиттеры частиц из простых эффектов в программируемые визуальные конструкторы. Вы можете экспериментировать: попробуйте заменить формулу розы на спираль (r = a * angle), лемнискату или фигуру Лиссажу. Источником может выступать не только математическая функция, но и заранее подготовленный массив точек, например, очертание спрайта или путь, пройденный игроком. Это открывает возможности для создания следов за заклинаниями, динамических границ силовых полей или частиц, выстраивающихся в логотип.
