О чем этот пример
При разработке игр часто возникает задача динамически изменять игровое пространство — например, убирать платформы или создавать проходимые участки в стенах. В Phaser для этого есть удобный метод `setEmpty()` у геометрического объекта `Rectangle`. Эта статья покажет, как с его помощью создавать интерактивную сетку, где клик «стирает» ячейку, делая её пустой для отрисовки и потенциальных физических расчётов. Этот приём полезен для создания разрушаемых уровней, редакторов карт или интерактивных пазлов.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
create ()
{
const graphics = this.add.graphics({ fillStyle: { color: 0x0000ff }, lineStyle: { color: 0x0000aa } });
const rectangles = [];
for (let x = 0; x < 10; x++)
{
rectangles[x] = [];
for (let y = 0; y < 10; y++)
{
rectangles[x][y] = new Phaser.Geom.Rectangle(x * 80, y * 60, 80, 60);
}
}
this.input.on('pointerdown', pointer =>
{
const x = Math.floor(pointer.x / 80);
const y = Math.floor(pointer.y / 60);
rectangles[x][y].setEmpty();
redraw();
});
redraw();
function redraw ()
{
graphics.clear();
for (let x = 0; x < 10; x++)
{
for (let y = 0; y < 10; y++)
{
graphics.fillRectShape(rectangles[x][y]);
graphics.strokeRectShape(rectangles[x][y]);
}
}
}
}
}
const config = {
width: 800,
height: 600,
type: Phaser.AUTO,
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Подготовка сцены и создание сетки прямоугольников
В методе create() сцены мы сначала создаём объект Graphics для рисования. Затем формируем двумерный массив rectangles, который будет хранить 100 объектов Phaser.Geom.Rectangle (10x10). Каждый прямоугольник имеет размер 80x60 пикселей и позиционируется с шагом по этим же значениям, образуя аккуратную сетку.
const graphics = this.add.graphics({ fillStyle: { color: 0x0000ff }, lineStyle: { color: 0x0000aa } });
const rectangles = [];
for (let x = 0; x < 10; x++)
{
rectangles[x] = [];
for (let y = 0; y < 10; y++)
{
rectangles[x][y] = new Phaser.Geom.Rectangle(x * 80, y * 60, 80, 60);
}
}
Обработка клика и вызов setEmpty()
Мы навешиваем обработчик события 'pointerdown' на сцену. При клике координаты курсора (pointer.x и pointer.y) преобразуются в индексы массива rectangles путём деления на размер ячейки с округлением вниз (Math.floor). Это позволяет найти прямоугольник, в который попал клик.
this.input.on('pointerdown', pointer =>
{
const x = Math.floor(pointer.x / 80);
const y = Math.floor(pointer.y / 60);
rectangles[x][y].setEmpty();
redraw();
});
Ключевой момент — вызов метода setEmpty() у найденного прямоугольника. Этот метод сбрасывает ширину и высоту объекта Rectangle в ноль, фактически делая его «пустым». После изменения состояния сетки мы вызываем функцию redraw() для обновления изображения.
Функция перерисовки и визуальный результат
Функция redraw() очищает холст graphics и заново рисует все прямоугольники из массива. Для отрисовки используются методы fillRectShape() (заливка) и strokeRectShape() (обводка).
function redraw ()
{
graphics.clear();
for (let x = 0; x < 10; x++)
{
for (let y = 0; y < 10; y++)
{
graphics.fillRectShape(rectangles[x][y]);
graphics.strokeRectShape(rectangles[x][y]);
}
}
}
Важно понять: когда у прямоугольника вызван setEmpty(), его ширина и высота равны нулю. Поэтому методы fillRectShape() и strokeRectShape() для такого объекта ничего не нарисуют — ячейка визуально исчезнет с экрана. Однако сам объект Rectangle остаётся в массиве, просто в «нулевом» состоянии.
Зачем это нужно? Практическое применение
Метод setEmpty() — это не просто способ скрыть графику. В контексте игровой логики он может отмечать область как «несуществующую». Например, если вы используете Phaser.Physics.Arcade и проверяете столкновения игрока с прямоугольниками из этого массива, «пустой» прямоугольник (с нулевыми размерами) просто не будет участвовать в коллизиях. Это открывает возможности для:
* **Динамического изменения уровня:** Удаление кирпичей, платформ или стен при выстреле или клике.
* **Создания порталов или скрытых зон:** Область можно «открыть» и сделать проходимой.
* **Построения простого редактора карт:** Где клик добавляет или убирает препятствие.
Помните, что setEmpty() — это метод геометрического объекта. Для полного удаления спрайта или физического тела из игры нужны другие подходы, например, destroy().
Что попробовать дальше
Метод setEmpty() у Phaser.Geom.Rectangle — это лёгкий способ перевести геометрическую область в «нулевое» состояние, что полезно для интерактивного управления игровым пространством. Для экспериментов попробуйте: изменить логику так, чтобы клик не стирал, а восстанавливал ячейку (используя setSize()); связать каждый прямоугольник с физическим телом (Arcade.Sprite) и отключать его физику при вызове setEmpty(); или реализовать «кисть» для закрашивания нескольких ячеек за один заход.
