О чем этот пример
В разработке игр часто возникает необходимость определить, находится ли курсор мыши или объект внутри определённой области. Механика кликов по кнопкам, выбор юнитов, зоны активации — всё это требует проверки на попадание точки в фигуру. В этой статье мы разберём, как эффективно использовать встроенный геометрический API Phaser для такой проверки на примере круга. Этот подход экономит ресурсы и упрощает код по сравнению с ручными расчётами.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
create ()
{
const graphics = this.add.graphics({ fillStyle: { color: 0xff0000 } });
const circle = new Phaser.Geom.Circle(400, 300, 200);
graphics.fillCircleShape(circle);
this.input.on('pointermove', pointer =>
{
graphics.clear();
if (circle.contains(pointer.x, pointer.y))
{
graphics.fillStyle(0x00ff00);
}
else
{
graphics.fillStyle(0xff0000);
}
graphics.fillCircleShape(circle);
});
}
}
const config = {
width: 800,
height: 600,
type: Phaser.AUTO,
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Создание геометрического объекта Circle
В Phaser геометрические фигуры, такие как круг, прямоугольник или треугольник, представлены отдельными объектами. Они являются "математическими" и не отрисовываются на сцене автоматически. Их главная цель — предоставлять удобные методы для расчётов, например, проверки на пересечение или попадание точки.
Создадим объект круга. Для этого используется класс Phaser.Geom.Circle. В его конструктор мы передаём три параметра: координаты центра по осям X и Y и радиус.
const circle = new Phaser.Geom.Circle(400, 300, 200);
Здесь мы создаём круг с центром в точке (400, 300) и радиусом 200 пикселей. Эти координаты заданы относительно сцены, которая в нашем примере имеет размеры 800x600.
Отрисовка фигуры с помощью Graphics
Чтобы визуализировать наш круг на сцене, мы используем объект Graphics. Это мощный инструмент для программной отрисовки примитивов: линий, фигур и заливок.
Сначала создаём объект graphics и сразу задаём стиль заливки красным цветом.
const graphics = this.add.graphics({ fillStyle: { color: 0xff0000 } });
Затем, чтобы нарисовать наш круг, вызываем метод fillCircleShape. Этот метод принимает в качестве аргумента именно геометрический объект Phaser.Geom.Circle.
graphics.fillCircleShape(circle);
Теперь на сцене появится красный круг.
Обработка движения курсора и проверка попадания
Суть примера — менять цвет круга в зависимости от того, находится ли курсор мыши внутри него. Для этого мы подписываемся на событие движения указателя pointermove.
Внутри обработчика события мы получаем объект pointer, который содержит текущие координаты курсора (pointer.x, pointer.y).
this.input.on('pointermove', pointer => {
// Код обработчика
});
Первым делом в обработчике мы очищаем предыдущую отрисовку, чтобы перерисовать круг новым цветом.
graphics.clear();
Затем происходит ключевая проверка. У объекта circle есть метод contains(), который принимает координаты точки (X, Y) и возвращает true, если точка находится внутри круга, включая его границу.
if (circle.contains(pointer.x, pointer.y))
{
graphics.fillStyle(0x00ff00); // Зелёный, если внутри
}
else
{
graphics.fillStyle(0xff0000); // Красный, если снаружи
}
После установки нового цвета мы снова вызываем fillCircleShape(circle) для отрисовки круга уже с обновлённым цветом.
Сборка конфигурации и запуск игры
Как и в любом проекте Phaser, нам необходимо создать базовую конфигурацию игры и запустить её экземпляр.
Конфигурационный объект config определяет размеры холста, автоматический выбор рендерера (Phaser.AUTO), контейнер на странице и главную сцену.
const config = {
width: 800,
height: 600,
type: Phaser.AUTO,
parent: 'phaser-example',
scene: Example // Наш класс сцены
};
Игра создаётся путём инстанцирования класса Phaser.Game с этой конфигурацией.
const game = new Phaser.Game(config);
После этого Phaser берёт на себя управление циклом рендеринга, вводом и запуском нашей сцены Example.
Что попробовать дальше
Использование встроенных геометрических объектов Phaser, таких как Phaser.Geom.Circle, делает код чище и производительнее. Метод contains() избавляет нас от необходимости вручную реализовывать проверку по формуле расстояния до центра. Этот паттерн можно легко адаптировать для других фигур (Rectangle, Triangle, Ellipse), у которых также есть свои методы contains. Для экспериментов попробуйте: добавить в сцену несколько кругов разного радиуса и проверять попадание в каждый из них; реализовать перетаскиваемый круг, который меняет цвет при наведении; или использовать эту логику для создания невидимой зоны активации для игрового объекта.
