О чем этот пример
При создании визуальных эффектов, таких как огонь, магия или дым, часто нужно, чтобы частицы исчезали не просто по таймеру, а при попадании в определённую область. В Phaser для этого предусмотрены Death Zones (зоны смерти). Эта статья покажет, как создать собственную, составную зону смерти любой формы, используя простую геометрию. Вы научитесь тонко управлять жизненным циклом частиц, что критически важно для создания атмосферных и реалистичных эффектов в играх.
Версия 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 rect1 = new Phaser.Geom.Rectangle(100, 50, 100, 100);
const rect2 = new Phaser.Geom.Rectangle(200, 350, 400, 200);
const rect3 = new Phaser.Geom.Rectangle(550, 150, 200, 100);
const rectangles = {
contains: function (x, y)
{
return Phaser.Geom.Rectangle.Contains(rect1, x, y) ||
Phaser.Geom.Rectangle.Contains(rect2, x, y) ||
Phaser.Geom.Rectangle.Contains(rect3, x, y);
}
};
const particles = this.add.particles('flares');
particles.createEmitter({
frame: [ 'red', 'green', 'blue' ],
x: 400,
y: 100,
speed: 300,
gravityY: 400,
lifespan: 4000,
scale: 0.4,
blendMode: 'ADD',
deathZone: { type: 'onEnter', source: rectangles }
});
const graphics = this.add.graphics();
graphics.lineStyle(1, 0x00ff00, 1);
graphics.strokeRectShape(rect1);
graphics.strokeRectShape(rect2);
graphics.strokeRectShape(rect3);
}
}
const config = {
type: Phaser.WEBGL,
width: 800,
height: 600,
backgroundColor: '#000',
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Что такое Death Zone?
В конфигурации эмиттера частиц Phaser параметр deathZone определяет область, при взаимодействии с которой частицы уничтожаются. Это невидимая граница, которая может быть двух типов:
- onEnter: Частица уничтожается в момент входа в зону.
- onLeave: Частица уничтожается в момент выхода из зоны.
Источником зоны (source) может быть любой объект, реализующий метод contains(x, y). Phaser предоставляет встроенные геометрические объекты, такие как Phaser.Geom.Rectangle или Phaser.Geom.Circle, но вы можете создать и свою собственную, сложную фигуру.
Создание пользовательской зоны смерти
В примере мы создаём не одну, а три прямоугольные зоны, объединённые в один логический объект. Это демонстрирует гибкость подхода: зона смерти не обязана быть простой фигурой.
Сначала создаются три геометрических прямоугольника (Phaser.Geom.Rectangle), определяющие области на сцене.
const rect1 = new Phaser.Geom.Rectangle(100, 50, 100, 100);
const rect2 = new Phaser.Geom.Rectangle(200, 350, 400, 200);
const rect3 = new Phaser.Geom.Rectangle(550, 150, 200, 100);
Затем создаётся пользовательский объект rectangles. Ключевой элемент — его метод contains(x, y). Этот метод будет автоматически вызываться движком частиц для проверки каждой частицы.
const rectangles = {
contains: function (x, y)
{
return Phaser.Geom.Rectangle.Contains(rect1, x, y) ||
Phaser.Geom.Rectangle.Contains(rect2, x, y) ||
Phaser.Geom.Rectangle.Contains(rect3, x, y);
}
};
Метод проверяет, находится ли переданная точка (координаты частицы) внутри ЛЮБОГО из трёх прямоугольников, используя статический метод Phaser.Geom.Rectangle.Contains. Если условие выполняется, метод возвращает true, и частица, для которой задана зона смерти типа onEnter, будет немедленно уничтожена.
Настройка эмиттера частиц
Создаётся менеджер частиц и эмиттер. Внимание стоит обратить на параметр deathZone в конфигурации эмиттера.
const particles = this.add.particles('flares');
particles.createEmitter({
frame: [ 'red', 'green', 'blue' ],
x: 400,
y: 100,
speed: 300,
gravityY: 400,
lifespan: 4000,
scale: 0.4,
blendMode: 'ADD',
deathZone: { type: 'onEnter', source: rectangles }
});
Эмиттер настроен так:
- Частицы испускаются из точки (400, 100).
- Им задана начальная скорость и гравитация, чтобы они летели по параболе.
- lifespan: 4000 — это запасной вариант: частица уничтожится через 4 секунды, если не попадёт в зону смерти.
- deathZone ссылается на наш пользовательский объект rectangles. Тип onEnter означает мгновенное уничтожение при попадании в зону.
Визуализация зон для отладки
Поскольку зоны смерти невидимы, для отладки и наглядности в примере они отрисовываются на сцене с помощью графического объекта (Graphics).
const graphics = this.add.graphics();
graphics.lineStyle(1, 0x00ff00, 1);
graphics.strokeRectShape(rect1);
graphics.strokeRectShape(rect2);
graphics.strokeRectShape(rect3);
Создаётся объект graphics, задаётся стиль линии (зелёный, толщиной 1 пиксель), а затем контуры всех трёх прямоугольников отрисовываются на сцене. В финальной игре этот код обычно удаляется, оставляя только логику работы зон.
Практическое применение и идеи
Такой подход открывает множество возможностей: 1. **Ограничение эффектов:** Дым от костра не должен выходить за пределы пещеры. Создайте зону смерти по её контуру. 2. **Взаимодействие с окружением:** Частицы воды или кислоты исчезают ("впитываются") при контакте с землёй или特定ными объектами. 3. **Сложные формы:** Вы можете описать любую многоугольную область, проверяя вхождение точки в неё с помощью алгоритма "луч-многоугольник".
Вот как может выглядеть зона в форме кольца (окружности с "дыркой" внутри):
const ringZone = {
contains: function(x, y) {
const distToCenter = Phaser.Math.Distance.Between(400, 300, x, y);
// Точка в зоне, если расстояние больше 50, но меньше 100
return distToCenter > 50 && distToCenter < 100;
}
};
Просто передайте этот объект как source в deathZone.
Что попробовать дальше
Death Zones в Phaser — мощный инструмент для контроля над визуальными эффектами. Используя пользовательские объекты с методом contains, вы можете создавать зоны смерти любой сложности, выходя далеко за рамки стандартных прямоугольников и кругов. Для экспериментов попробуйте создать зону в форме лабиринта, зону, которая движется вместе с игровым персонажем, или зону, которая меняет свою форму со временем, создавая динамичные и запоминающиеся эффекты.
