О чем этот пример
При создании визуальных эффектов, таких как частицы, часто требуется проверять их взаимодействие с другими объектами игры или отлаживать их поведение. Например, для определения столкновений или точного позиционирования. В этой статье мы разберем, как в Phaser получить границы (bounding box) каждой активной частицы и визуализировать их для отладки. Это полезно не только для отладки, но и для реализации нестандартной логики, связанной с областью влияния частиц.
Версия 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('jellies', 'assets/atlas/jellies.png', 'assets/atlas/jellies.json');
}
create ()
{
this.emitter = this.add.particles(0, 0, 'jellies', {
frame: [ 'WithShadow/Jelly5', 'WithShadow/Jelly2', 'WithShadow/Jelly4' ],
scale: { start: 1, end: 0 },
rotate: { start: 0, end: 360 },
speed: { min: 200, max: 250 },
lifespan: 2000,
emitting: false
});
this.input.on('pointerdown', () =>
{
this.emitter.emitParticleAt(400, 300);
});
this.graphics = this.add.graphics();
this.add.text(16, 16, 'Click to release a particle');
}
update ()
{
this.graphics.clear();
this.graphics.lineStyle(1, 0x00ff00);
this.emitter.forEachAlive(particle => {
this.graphics.strokeRectShape(particle.getBounds());
});
}
}
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
backgroundColor: '#2d2d88',
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Создание эмиттера частиц
В методе create() сцены создается источник частиц (ParticleEmitter). Он настраивается на использование атласа jellies и будет испускать частицы с одним из трех кадров (frame). Эмиттер изначально не активен (emitting: false), а частицы будут выпускаться по щелчку мыши.
Частицы получают анимацию изменения масштаба (scale), вращения (rotate) и случайную скорость (speed). Их время жизни (lifespan) установлено в 2000 миллисекунд.
this.emitter = this.add.particles(0, 0, 'jellies', {
frame: [ 'WithShadow/Jelly5', 'WithShadow/Jelly2', 'WithShadow/Jelly4' ],
scale: { start: 1, end: 0 },
rotate: { start: 0, end: 360 },
speed: { min: 200, max: 250 },
lifespan: 2000,
emitting: false
});
По клику мыши в позицию (400, 300) испускается одна частица с помощью метода emitParticleAt().
this.input.on('pointerdown', () => {
this.emitter.emitParticleAt(400, 300);
});
Визуализация границ с помощью Graphics
Для отрисовки контуров (границ) частиц создается объект Graphics (this.graphics). Этот объект будет перерисовываться каждый кадр в методе update().
this.graphics = this.add.graphics();
В update() сначала очищается предыдущее содержимое Graphics, затем устанавливается стиль линии толщиной 1 пиксель зеленого цвета.
this.graphics.clear();
this.graphics.lineStyle(1, 0x00ff00);
Итерация по частицам и получение их границ
Ключевой метод для работы с активными частицами — forEachAlive(). Он перебирает все частицы эмиттера, у которых еще не истек срок жизни (lifespan).
Для каждой такой частицы вызывается метод getBounds(). Этот метод возвращает объект типа Phaser.Geom.Rectangle, содержащий координаты, ширину и высоту ограничивающего прямоугольника частицы на основе ее текущей трансформации (позиция, масштаб, вращение).
this.emitter.forEachAlive(particle => {
this.graphics.strokeRectShape(particle.getBounds());
});
Метод strokeRectShape() объекта Graphics принимает этот прямоугольник и рисует его контур. Таким образом, вокруг каждой летящей и меняющейся частицы появляется зеленая рамка, точно соответствующая ее визуальным границам.
Конфигурация игры и практическое применение
Пример использует стандартную конфигурацию игры Phaser. Важно, что отрисовка границ происходит в update(), то есть каждый кадр, что обеспечивает актуальную визуализацию для движущихся объектов.
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
backgroundColor: '#2d2d88',
parent: 'phaser-example',
scene: Example
};
Получение границ частицы через getBounds() — это мощный инструмент отладки. Вы можете использовать возвращаемый объект Rectangle не только для рисования, но и для проверки пересечений с другими прямоугольниками (Phaser.Geom.Intersects.RectangleToRectangle), что открывает возможности для кастомной логики столкновений частиц с игровым миром.
Что попробовать дальше
Метод getBounds() для частиц в Phaser предоставляет простой способ получить их текущие геометрические границы в мировых координатах. Это незаменимо для отладки сложных визуальных эффектов и реализации своей логики взаимодействия, когда стандартной физики недостаточно.
Для экспериментов попробуйте: изменить форму границ на эллипс, используя данные о размере частицы; реализовать логику, где частица исчезает при пересечении ее границ с определенной областью экрана; или привязать к границам частицы другой графический эффект.
