О чем этот пример
В создании игр часто требуется измерять дистанцию между объектами. Мы привыкли к евклидову расстоянию (прямая линия) или манхэттенскому (сумма по осям). Но есть и третий, мощный вариант — расстояние Чебышёва, которое идеально подходит для сеточных миров, ходьбы короля в шахматах или определения зоны обнаружения врага в виде квадрата. В этой статье разберем, как использовать `Phaser.Math.Distance.Chebyshev` на практике, чтобы легко создавать квадратные области влияния и детекторы приближения.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
graphic;
ufo;
player;
cursors;
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('eyes', 'assets/sprites/slimeeyes.png');
this.load.image('ufo', 'assets/sprites/ufo.png');
}
create ()
{
this.cursors = this.input.keyboard.createCursorKeys();
this.player = this.add.image(400, 300, 'eyes');
this.ufo = this.add.image(200, 150, 'ufo');
this.graphic = this.add.graphics({ lineStyle: { color: 0x00ffff } });
}
update ()
{
if (this.cursors.left.isDown)
{
this.player.x -= 5;
}
else if (this.cursors.right.isDown)
{
this.player.x += 5;
}
if (this.cursors.up.isDown)
{
this.player.y -= 5;
}
else if (this.cursors.down.isDown)
{
this.player.y += 5;
}
const dist = Phaser.Math.Distance.Chebyshev(this.player.x, this.player.y, this.ufo.x, this.ufo.y);
this.graphic
.clear()
.strokeRect(this.player.x - dist, this.player.y - dist, 2 * dist, 2 * dist);
}
}
const config = {
type: Phaser.AUTO,
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Что такое расстояние Чебышёва?
В отличие от привычного евклидова расстояния (корень из суммы квадратов разностей), расстояние Чебышёва определяется как максимум из абсолютных разностей координат по осям X и Y.
Грубо говоря, это длина стороны квадрата, в который можно заключить две точки, если его стороны параллельны осям координат. Именно это свойство делает его невероятно полезным для игр с сеточной или клеточной логикой, где движение возможно в 8 направлениях (как король в шахматах).
const dist = Phaser.Math.Distance.Chebyshev(x1, y1, x2, y2);
// dist = Math.max(Math.abs(x1 - x2), Math.abs(y1 - y2))
Структура примера: сцена, объекты и графика
В примере создается базовая сцена Phaser с тремя ключевыми объектами: игроком (player), НЛО (ufo) и графическим контейнером (graphic). Игрок управляется стрелками клавиатуры, НЛО статично. Графический объект будет использоваться для визуализации.
preload() {
this.load.image('eyes', 'assets/sprites/slimeeyes.png');
this.load.image('ufo', 'assets/sprites/ufo.png');
}
create() {
this.cursors = this.input.keyboard.createCursorKeys();
this.player = this.add.image(400, 300, 'eyes');
this.ufo = this.add.image(200, 150, 'ufo');
this.graphic = this.add.graphics({ lineStyle: { color: 0x00ffff } });
}
Расчет и визуализация в реальном времени
В методе update() происходит магия. Сначала обрабатывается ввод с клавиатуры для перемещения спрайта игрока. Затем, на каждом кадре, вычисляется расстояние Чебышёва между центром спрайта игрока и центром НЛО с помощью Phaser.Math.Distance.Chebyshev.
Полученное значение dist — это радиус квадрата (половина его стороны). Чтобы нарисовать квадрат, центр которого находится на игроке, мы вычисляем его левый верхний угол как (player.x - dist, player.y - dist), а ширину и высоту как 2 * dist.
update() {
// ... обработка управления игроком ...
const dist = Phaser.Math.Distance.Chebyshev(this.player.x, this.player.y, this.ufo.x, this.ufo.y);
this.graphic
.clear()
.strokeRect(this.player.x - dist, this.player.y - dist, 2 * dist, 2 * dist);
}
Важно: метод .clear() вызывается каждый кадр, чтобы стереть предыдущий квадрат и нарисовать новый, соответствующий текущему расстоянию.
Практическое применение в играх
Зачем это нужно? Эта техника отлично подходит для: 1. **Квадратных зон обнаружения:** Если враг должен "увидеть" игрока только когда тот находится в пределах определенного квадрата вокруг него. 2. **Областей эффектов (AoE):** Для мгновенных или постоянных эффектов (яд, благословение), действующих в квадратной области. 3. **Поведения NPC:** Задание патрульной зоны в виде квадрата или определение, когда игрок вошел в "личное пространство" персонажа.
Проверка попадания в такую зону становится тривиальной:
if (Phaser.Math.Distance.Chebyshev(player.x, player.y, guard.x, guard.y) <= guardVisionRadius) {
// Охранник обнаружил игрока!
}
Что попробовать дальше
Расстояние Чебышёва — это элегантный и производительный инструмент для работы с квадратными областями в играх на Phaser. Оно избавляет от необходимости проверять две координаты отдельно и идеально ложится на сеточную логику. **Идеи для экспериментов:** 1. Сделайте так, чтобы НЛО начинало преследовать игрока, когда тот заходит в квадратную зону. 2. Реализуйте "минное поле": разместите несколько статичных мин и визуализируйте опасную зону вокруг каждой, когда игрок приближается. 3. Используйте это расстояние для создания пошаговой тактической игры, где юниты могут атаковать цели в пределах квадрата определенного размера.
