О чем этот пример
При разработке игр часто возникает задача определить точку пересечения линии и геометрической фигуры. Например, для расчета траектории снаряда, проверки видимости врага или позиции прицела. Встроенные методы Phaser.Geom позволяют решать такие задачи без сложной математики. В этой статье разберем, как с помощью `Phaser.Geom.Rectangle.PerimeterPoint()` находить точку на границе прямоугольника по заданному углу и визуализировать результат.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
sprite;
point;
rect;
graphics;
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('mushroom', 'assets/sprites/mushroom2.png');
}
create ()
{
this.graphics = this.add.graphics({ lineStyle: { width: 2, color: 0x00ff00 }, fillStyle: { color: 0xff0000 }});
this.sprite = this.add.sprite(500, 100, 'mushroom');
this.rect = new Phaser.Geom.Rectangle(350, 300, 200, 128);
this.point = new Phaser.Geom.Rectangle(0, 0, 8, 8);
this.input.on('pointermove', (pointer) =>
{
this.sprite.setPosition(pointer.worldX, pointer.worldY);
});
}
update ()
{
const angle = Phaser.Math.Angle.Between(this.sprite.x, this.sprite.y, this.rect.centerX, this.rect.centerY);
Phaser.Geom.Rectangle.PerimeterPoint(this.rect, Phaser.Math.RadToDeg(angle) + 180, this.point);
this.graphics.clear();
this.graphics.strokeRectShape(this.rect);
this.graphics.fillRect(this.point.x - 4, this.point.y - 4, this.point.width, this.point.height);
// Draw a line from the center of the rect to the point on the perimeter
this.graphics.lineStyle(2, 0xffffff);
this.graphics.beginPath();
this.graphics.moveTo(this.rect.centerX, this.rect.centerY);
this.graphics.lineTo(this.point.x, this.point.y);
this.graphics.closePath();
this.graphics.strokePath();
}
}
const config = {
width: 800,
height: 600,
type: Phaser.AUTO,
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Подготовка сцены и объектов
В методе preload загружается спрайт, а в create инициализируются ключевые объекты.
Создается графический объект graphics для отрисовки линий и фигур. Спрайт sprite (гриб) будет следовать за курсором. Прямоугольник rect задает статичную область на сцене. Объект point — это небольшой прямоугольник, который будет визуализировать найденную точку.
Обработчик события pointermove обновляет позицию спрайта.
this.graphics = this.add.graphics({ lineStyle: { width: 2, color: 0x00ff00 }, fillStyle: { color: 0xff0000 }});
this.sprite = this.add.sprite(500, 100, 'mushroom');
this.rect = new Phaser.Geom.Rectangle(350, 300, 200, 128);
this.point = new Phaser.Geom.Rectangle(0, 0, 8, 8);
this.input.on('pointermove', (pointer) => {
this.sprite.setPosition(pointer.worldX, pointer.worldY);
});
Расчет угла и точки на границе
В методе update для каждого кадра вычисляется угол от центра спрайта к центру прямоугольника. Функция Phaser.Math.Angle.Between возвращает угол в радианах.
Затем вызывается ключевой метод Phaser.Geom.Rectangle.PerimeterPoint. Он принимает три аргумента: исходный прямоугольник, угол в градусах и объект точки (или любой объект с полями `x,y), куда будет записан результат. Угол передается в градусах, поэтому используетсяPhaser.Math.RadToDeg`. Прибавление 180 градусов инвертирует направление луча: теперь он идет из центра прямоугольника к спрайту.
const angle = Phaser.Math.Angle.Between(this.sprite.x, this.sprite.y, this.rect.centerX, this.rect.centerY);
Phaser.Geom.Rectangle.PerimeterPoint(this.rect, Phaser.Math.RadToDeg(angle) + 180, this.point);
Визуализация результата
После расчетов необходимо очистить графику от предыдущего кадра и нарисовать все заново.
Сначала отрисовывается контур основного прямоугольника с помощью strokeRectShape. Затем заливается красный квадратик в найденной точке. Так как this.point — это прямоугольник, для его центрирования используются координаты this.point.x - 4 и this.point.y - 4.
Наконец, рисуется белая линия от центра прямоугольника до найденной точки на периметре, чтобы визуально показать луч.
this.graphics.clear();
this.graphics.strokeRectShape(this.rect);
this.graphics.fillRect(this.point.x - 4, this.point.y - 4, this.point.width, this.point.height);
this.graphics.lineStyle(2, 0xffffff);
this.graphics.beginPath();
this.graphics.moveTo(this.rect.centerX, this.rect.centerY);
this.graphics.lineTo(this.point.x, this.point.y);
this.graphics.closePath();
this.graphics.strokePath();
Конфигурация и запуск игры
Стандартная конфигурация игры Phaser 3. Задается размер холста, тип рендерера (Phaser.AUTO выбирает WebGL или Canvas автоматически), родительский элемент для встраивания и стартовая сцена.
const config = {
width: 800,
height: 600,
type: Phaser.AUTO,
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Что попробовать дальше
Метод PerimeterPoint — мощный инструмент для работы с геометрией в играх. Он идеально подходит для расчета точек столкновения лучей (например, для оружия), позиций спавна объектов по краям зоны или определения границ камеры. Для экспериментов попробуйте заменить статичный прямоугольник на движущийся объект, использовать несколько лучей для создания "радара" или применить этот метод к другим геометрическим фигурам из модуля Phaser.Geom.
