О чем этот пример
В игровом мире всё вращается вокруг расстояний. Определяет ли враг игрока, достигает ли снаряд цели, или визуальный эффект реагирует на приближение — всё это требует расчёта дистанции. В этой статье мы разберём практический пример из официальной документации Phaser, который показывает, как просто и эффективно использовать `Phaser.Math.Distance.Between` для создания динамической визуализации радиуса действия между двумя спрайтами. Этот подход — основа для механик агро, индикаторов приближения и много другого.
Версия 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.Between(this.player.x, this.player.y, this.ufo.x, this.ufo.y);
this.graphic
.clear()
.strokeCircle(this.player.x, this.player.y, dist);
}
}
const config = {
type: Phaser.AUTO,
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Подготовка сцены и загрузка ресурсов
Класс Example наследуется от Phaser.Scene. В методе preload() мы загружаем два изображения-спрайта с удалённого базового URL. Это стандартный подход для быстрого прототипирования с использованием ресурсов из репозитория примеров Phaser.
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.input.keyboard.createCursorKeys(), добавляются два спрайта на сцену в определённых координатах, а также создаётся объект Graphics для рисования. Обратите внимание, что this.graphic создаётся с предустановленным стилем линии голубого цвета.
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(). Здесь мы обрабатываем состояние клавиш-стрелок. В зависимости от нажатой клавиши, координаты `xилиyспрайтаthis.playerизменяются на фиксированную величину (5` пикселей). Это реализация самого простого пошагового управления.
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;
}
Расчёт расстояния и динамическое рисование
Самая важная часть примера. На каждом кадре, после обновления позиции игрока, мы вычисляем расстояние между ним и НЛО с помощью статического метода Phaser.Math.Distance.Between. Метод принимает четыре аргумента: координаты X и Y первой точки (игрок) и координаты X и Y второй точки (НЛО), возвращая числовое значение — евклидово расстояние между ними.
const dist = Phaser.Math.Distance.Between(this.player.x, this.player.y, this.ufo.x, this.ufo.y);
Полученное расстояние dist используется как радиус для рисования круга. Объект this.graphic сначала очищается методом .clear() от рисунков предыдущего кадра, а затем методом .strokeCircle() рисуется контур круга. Центр круга привязан к координатам игрока, а его радиус равен текущему расстоянию до НЛО. Это создаёт эффект "радиуса действия" или "силового поля", которое постоянно меняет размер.
this.graphic
.clear()
.strokeCircle(this.player.x, this.player.y, dist);
Конфигурация и запуск игры
Это стандартный конфигурационный объект для Phaser 3. Он указывает, что рендеринг должен быть выбран автоматически (Phaser.AUTO), задаёт ID HTML-элемента для встраивания игры и определяет основную сцену.
const config = {
type: Phaser.AUTO,
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Инициализация игры происходит созданием нового экземпляра Phaser.Game с переданной конфигурацией.
Что попробовать дальше
Пример наглядно демонстрирует, как всего одна строка кода с Phaser.Math.Distance.Between может стать мощным инструментом для геймдизайна и визуальной обратной связи. Для экспериментов попробуйте: изменить логику, чтобы круг рисовался вокруг НЛО; залить круг цветом, прозрачность которого зависит от расстояния; или добавить условие, при котором НЛО "просыпается" и начинает преследование, когда игрок заходит внутрь круга определённого радиуса.
