О чем этот пример
Создание динамических визуальных эффектов и управление отрисовкой объектов — частые задачи в игровой разработке. Метод `isEmpty()` для геометрических фигур в Phaser 3 предоставляет простой и эффективный способ управлять рендерингом на основе состояния объекта. В этой статье мы разберем практический пример, который демонстрирует, как использовать `Phaser.Geom.Circle.isEmpty()` для визуального различения "пустых" и "полных" кругов, что может быть полезно для интерактивных интерфейсов, анимаций или игровой логики, требующей условной отрисовки.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
circles;
graphics;
create ()
{
this.graphics = this.add.graphics({ lineStyle: { color: 0x00ff00 }, fillStyle: { color: 0x00ff00 }});
this.circles = [];
for (let y = 0; y < 6; y++)
{
for (let x = 0; x < 8; x++)
{
this.circles.push(new Phaser.Geom.Circle(50 + x * 100, 50 + y * 100, Phaser.Math.Between(-50, 50)));
}
}
}
update ()
{
this.graphics.clear();
for (let i = 0; i < this.circles.length; i++)
{
const circle = this.circles[i];
circle.radius += 0.5;
if (circle.radius >= 50)
{
circle.radius -= 100;
}
if (!circle.isEmpty())
{
this.graphics.fillCircleShape(circle);
}
else
{
this.graphics.strokeCircleShape(circle);
}
}
}
}
const config = {
width: 800,
height: 600,
type: Phaser.AUTO,
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Суть метода isEmpty()
В Phaser 3 класс Phaser.Geom.Circle представляет собой геометрический круг, определяемый координатами центра (x, y) и радиусом. Метод isEmpty() этого класса возвращает логическое значение true, если радиус круга меньше или равен нулю. В противном случае возвращается false.
Этот метод является частью геометрического API и не зависит от графического контекста или физического тела. Он проверяет исключительно математическое свойство фигуры. Визуально круг с нулевым или отрицательным радиусом не имеет площади, поэтому его можно считать "пустым".
const circle = new Phaser.Geom.Circle(100, 100, 30);
console.log(circle.isEmpty()); // false, так как радиус 30 > 0
circle.radius = 0;
console.log(circle.isEmpty()); // true, так как радиус равен 0
Структура сцены и инициализация
В примере создается сцена Example, которая наследуется от Phaser.Scene. В ней объявляются два свойства: circles для хранения массива объектов кругов и graphics для отрисовки.
В методе create() инициализируется графический объект this.graphics с заданными стилями линии и заливки зеленого цвета. Затем создается массив this.circles и заполняется в двойном цикле.
create ()
{
this.graphics = this.add.graphics({ lineStyle: { color: 0x00ff00 }, fillStyle: { color: 0x00ff00 }});
this.circles = [];
for (let y = 0; y < 6; y++)
{
for (let x = 0; x < 8; x++)
{
this.circles.push(new Phaser.Geom.Circle(50 + x * 100, 50 + y * 100, Phaser.Math.Between(-50, 50)));
}
}
}
Каждый круг создается с центром, расположенным в узлах сетки 8x6 с шагом 100 пикселей. Начальный радиус задается случайным образом в диапазоне от -50 до 50 с помощью Phaser.Math.Between. Это означает, что некоторые круги уже при создании могут иметь нулевой или отрицательный радиус и, следовательно, будут считаться "пустыми" (isEmpty() === true).
Динамическое обновление и условная отрисовка
Метод update() выполняется каждый кадр игры. В начале он очищает предыдущие отрисовки с помощью this.graphics.clear().
Затем в цикле перебираются все круги. Радиус каждого круга увеличивается на 0.5 пикселя за кадр. Когда радиус достигает или превышает 50, он уменьшается на 100. Эта арифметика создает циклическое "дыхание" радиуса, которое периодически переводит его в отрицательные значения и обратно.
circle.radius += 0.5;
if (circle.radius >= 50)
{
circle.radius -= 100;
}
После изменения радиуса вызывается метод `circle.isEmpty()`. В зависимости от его результата, круг отрисовывается по-разному:
- Если круг "не пустой" (радиус > 0), он заливается цветом с помощью `this.graphics.fillCircleShape(circle)`.
- Если круг "пустой" (радиус <= 0), отрисовывается только его контур с помощью `this.graphics.strokeCircleShape(circle)`.
if (!circle.isEmpty())
{
this.graphics.fillCircleShape(circle);
}
else
{
this.graphics.strokeCircleShape(circle);
}
Таким образом, на экране визуально различаются активные (залитые) круги и неактивные (только контур), состояние которых определяется простой математической проверкой.
Конфигурация и запуск игры
Код завершается стандартной для Phaser 3 конфигурацией игры, которая определяет размеры холста, тип рендерера, родительский контейнер в DOM и основную сцену.
const config = {
width: 800,
height: 600,
type: Phaser.AUTO,
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Эта конфигурация создает игровой экран размером 800x600 пикселей, автоматически выбирает WebGL или Canvas рендерер и монтирует его в элемент с id='phaser-example'. Объект игры инстанциируется с этой конфигурацией, после чего Phaser берет на себя управление циклом обновления и отрисовки.
Что попробовать дальше
Метод isEmpty() для геометрических фигур — это небольшой, но мощный инструмент для управления логикой отрисовки на основе состояния объекта. В рассмотренном примере он создает гипнотический эффект пульсирующей сетки кругов.
**Идеи для экспериментов:**
1. Измените условие в update(), чтобы круг исчезал полностью, а не переходил в контур, когда isEmpty() возвращает true.
2. Используйте проверку isEmpty() для управления не только графикой, но и игровой логикой, например, для деактивации коллизий с "пустыми" объектами.
3. Скомбинируйте этот подход с другими геометрическими методами, такими как contains() для проверки попадания точки, чтобы создавать интерактивные области, которые визуально реагируют на состояние.
