О чем этот пример
Определение попадания точки или объекта в заданную область — фундаментальная задача для игровой логики. Проверка столкновений, зоны активации событий, определение кликов по нестандартным фигурам — всё это требует быстрых и точных геометрических вычислений. В этой статье мы разберем, как использовать встроенные методы Phaser для проверки принадлежности точки кругу. Это не только проще и производительнее ручных расчетов, но и открывает путь к созданию сложной интерактивности, основанной на геометрии.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
a = 0;
graphics;
point;
circle;
create ()
{
this.graphics = this.add.graphics({ lineStyle: { width: 2, color: 0x00ff00 }, fillStyle: { color: 0xff0000 }});
this.circle = new Phaser.Geom.Circle(400, 300, 200);
this.point = new Phaser.Geom.Rectangle(0, 0, 16, 16);
}
update ()
{
this.a += 0.01;
if (this.a > Math.PI * 2)
{
this.a -= Math.PI * 2;
}
this.point.x = 400 - Math.cos(this.a) * 400;
this.point.y = 300 - Math.sin(this.a * 2) * 300;
this.graphics.clear();
this.graphics.strokeCircleShape(this.circle);
if (Phaser.Geom.Circle.ContainsPoint(this.circle, this.point))
{
this.graphics.fillStyle(0xff0000);
}
else
{
this.graphics.fillStyle(0x0000ff);
}
this.graphics.fillRect(this.point.x - 8, this.point.y - 8, this.point.width, this.point.height);
}
}
const config = {
width: 800,
height: 600,
type: Phaser.AUTO,
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Подготовка сцены и объектов
В методе create() инициализируются основные объекты, которые будут использоваться для визуализации и расчетов.
Создается объект Graphics для отрисовки. Ему сразу задаются стили линии (зеленая) и заливки (красная), которые будут применяться по умолчанию.
Затем создаются две геометрические фигуры:
1. Phaser.Geom.Circle — круг с центром в точке (400, 300) и радиусом 200 пикселей. Это наша целевая зона.
2. Phaser.Geom.Rectangle — прямоугольник размером 16x16 пикселей. В контексте примера он представляет собой точку (его верхний левый угол) для проверки.
this.graphics = this.add.graphics({ lineStyle: { width: 2, color: 0x00ff00 }, fillStyle: { color: 0xff0000 }});
this.circle = new Phaser.Geom.Circle(400, 300, 200);
this.point = new Phaser.Geom.Rectangle(0, 0, 16, 16);
Анимация движения точки
В методе update(), который вызывается каждый кадр, реализуется движение нашей "точки" (прямоугольника) по сложной траектории.
Угол `a` увеличивается на 0.01 радиана каждый кадр, создавая непрерывную анимацию. Когда значение превышает полный круг (2π), оно сбрасывается, чтобы избежать переполнения.
Координаты точки рассчитываются с использованием тригонометрических функций Math.cos и Math.sin. Обратите внимание, что для координаты `yугол умножается на 2 (this.a * 2`), что создает более сложную, "восьмеркообразную" траекторию Лиссажу, а не просто движение по окружности.
this.a += 0.01;
if (this.a > Math.PI * 2)
{
this.a -= Math.PI * 2;
}
this.point.x = 400 - Math.cos(this.a) * 400;
this.point.y = 300 - Math.sin(this.a * 2) * 300;
Очистка и отрисовка кадра
Перед каждой новой отрисовкой необходимо очистить холст Graphics от предыдущего кадра. Для этого используется метод clear().
После очистки отрисовывается контур нашего целевого круга с помощью метода strokeCircleShape(), который принимает объект Phaser.Geom.Circle.
this.graphics.clear();
this.graphics.strokeCircleShape(this.circle);
Ключевая проверка и визуальный ответ
Здесь происходит самое важное — проверка, находится ли текущая позиция точки внутри круга.
Для этого используется статический метод Phaser.Geom.Circle.ContainsPoint(). Он принимает два аргумента: объект круга и объект точки (или любой объект, имеющий свойства `xиy, как наш прямоугольникthis.point). Метод возвращаетtrueилиfalse`.
В зависимости от результата проверки, меняется цвет заливки у объекта Graphics. Если точка внутри круга — цвет красный (0xff0000), если снаружи — синий (0x0000ff).
Наконец, отрисовывается сама точка в виде залитого квадрата. Его центр позиционируется в координатах point.x и point.y.
if (Phaser.Geom.Circle.ContainsPoint(this.circle, this.point))
{
this.graphics.fillStyle(0xff0000);
}
else
{
this.graphics.fillStyle(0x0000ff);
}
this.graphics.fillRect(this.point.x - 8, this.point.y - 8, this.point.width, this.point.height);
Что попробовать дальше
Метод Phaser.Geom.Circle.ContainsPoint() предоставляет готовое, оптимизированное решение для проверки попадания точки в круг, избавляя разработчика от необходимости реализовывать формулу расстояния вручную.
**Идеи для экспериментов:**
1. Замените Phaser.Geom.Rectangle на объект игрока (sprite) и проверяйте его центр.
2. Создайте массив кругов-ловушек и проверяйте попадание в любой из них.
3. Используйте результат проверки не только для смены цвета, но и для начисления очков, активации механизмов или нанесения урона.
