О чем этот пример
При разработке игр часто возникает задача разместить объекты по периметру области или визуализировать границы. Вместо ручных вычислений можно использовать встроенные методы геометрии Phaser. В этой статье разберем, как получить равномерно распределенные точки на сторонах прямоугольника с помощью метода `getPoints` класса `Phaser.Geom.Rectangle`. Это полезно для создания патрульных маршрутов, границ уровня или декоративных элементов.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
create ()
{
const graphics = this.add.graphics({ lineStyle: { width: 1, color: 0x00ff00 }, fillStyle: { color: 0xffff00 }});
const rect = new Phaser.Geom.Rectangle(100, 100, 500, 400);
graphics.strokeRectShape(rect);
// Get 64 points around the rectangle
// var points = rect.getPoints(64);
// Every point will be 50px apart (note the 'false' given for the quantity argument)
// If the stepRate doesn't divide equally into the rectangle dimensions then you'll get offset values at the end
const points = rect.getPoints(false, 50);
for (let i = 0; i < points.length; i++)
{
const p = points[i];
graphics.fillRect(p.x - 4, p.y - 4, 8, 8);
}
}
}
const config = {
width: 800,
height: 600,
type: Phaser.AUTO,
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Создаем прямоугольник и графику
В примере мы работаем внутри метода create сцены. Сначала создаем объект graphics для отрисовки линий и фигур. Затем создаем прямоугольник с координатами (100, 100), шириной 500 и высотой 400 пикселей.
const graphics = this.add.graphics({ lineStyle: { width: 1, color: 0x00ff00 }, fillStyle: { color: 0xffff00 }});
const rect = new Phaser.Geom.Rectangle(100, 100, 500, 400);
Зеленой линией (strokeRectShape) рисуем контур прямоугольника, чтобы видеть его границы.
Метод getPoints: два режима работы
Ключевой метод rect.getPoints может работать в двух режимах. Первый аргумент определяет режим:
- Если передано число (например, 64), метод вернет указанное количество точек, равномерно распределенных по периметру.
- Если передано false, активируется второй режим: второй аргумент (stepRate) задает расстояние между точками в пикселях.
В примере используется второй режим с шагом 50 пикселей.
const points = rect.getPoints(false, 50);
Метод проходит по периметру прямоугольника, начиная с левого верхнего угла, и возвращает массив точек (Phaser.Geom.Point). Если шаг не делит стороны ровно, последние точки на каждой стороне могут сместиться.
Визуализация полученных точек
После получения массива точек мы можем их обработать. В примере каждая точка визуализируется желтым квадратом.
for (let i = 0; i < points.length; i++)
{
const p = points[i];
graphics.fillRect(p.x - 4, p.y - 4, 8, 8);
}
Цикл проходит по всем точкам. Для каждой точки `p` рисуется квадрат размером 8x8 пикселя, центрированный на координатах точки (смещение на -4 по осям).
Практическое применение: патрульные пути и границы
Полученные точки можно использовать не только для отрисовки. Например, их координаты идеально подходят для задания пути движения NPC вдоль стен.
// Предположим, у нас есть спрайт охранника
const guard = this.add.sprite(points[0].x, points[0].y, 'guard');
this.tweens.add({
targets: guard,
props: {
x: { value: points.map(p => p.x), duration: 10000 },
y: { value: points.map(p => p.y), duration: 10000 }
},
repeat: -1
});
Также точки можно использовать для расстановки коллайдеров, создания эффекта "огней" по периметру или для проверки, находится ли объект близко к границе.
Что попробовать дальше
Метод getPoints класса Phaser.Geom.Rectangle — мощный инструмент для работы с границами областей. Он избавляет от ручных расчетов и позволяет легко получать координаты для размещения объектов или задания движения.
Поэкспериментируйте: попробуйте разные значения stepRate, создайте несколько прямоугольников с разными точками, используйте точки для генерации частиц вдоль границ или для создания динамических барьеров, которые меняют форму во время игры.
