О чем этот пример
В игровой разработке часто требуется работать с геометрией: рассчитывать траектории, области поражения или точки спавна объектов. Одна из полезных, но неочевидных операций — нахождение центра треугольника. В отличие от простого среднего арифметического, инцентр (incenter) — это точка, равноудалённая от всех сторон фигуры. В этой статье разберём, как использовать `Phaser.Geom.Triangle.InCenter()` для точных геометрических расчётов в вашей игре, например, для размещения объекта в самом "безопасном" месте зоны или для построения AI, который обходит углы.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
create ()
{
const graphics = this.add.graphics({ lineStyle: { width: 2, color: 0x00ff00 }, fillStyle: { color: 0xffff00 } });
// Create a random triangle
const x1 = Phaser.Math.Between(100, 700);
const y1 = Phaser.Math.Between(50, 550);
const x2 = Phaser.Math.Between(100, 700);
const y2 = Phaser.Math.Between(50, 550);
const x3 = Phaser.Math.Between(100, 700);
const y3 = Phaser.Math.Between(50, 550);
const triangle = new Phaser.Geom.Triangle(x1, y1, x2, y2, x3, y3);
graphics.strokeTriangleShape(triangle);
// Get the inCenter of the triangle
const incenter = Phaser.Geom.Triangle.InCenter(triangle);
// Draw lines from each point of the triangle to the center
graphics.lineStyle(1, 0x00ff00);
graphics.lineBetween(x1, y1, incenter.x, incenter.y);
graphics.lineBetween(x2, y2, incenter.x, incenter.y);
graphics.lineBetween(x3, y3, incenter.x, incenter.y);
// Draw the center
graphics.fillPointShape(incenter, 4);
}
}
const config = {
width: 800,
height: 600,
type: Phaser.AUTO,
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Что такое инцентр треугольника?
Инцентр — это точка пересечения биссектрис всех трёх углов треугольника. Главное свойство: расстояния от инцентра до каждой из сторон фигуры равны. Это делает его идеальным кандидатом для размещения объекта, который должен находиться «внутри» зоны, не примыкая к краям.
В игровом контексте это может быть: * Точка для спавна босса в центре арены сложной формы. * Цель для камеры при обзоре треугольного участка карты. * Опорная точка для расчёта физических или визуальных эффектов.
Создаём случайный треугольник
Для демонстрации сначала нарисуем произвольный треугольник. В Phaser для этого используется класс Phaser.Geom.Triangle. Мы зададим три случайные вершины в пределах сцены с помощью Phaser.Math.Between.
const x1 = Phaser.Math.Between(100, 700);
const y1 = Phaser.Math.Between(50, 550);
const x2 = Phaser.Math.Between(100, 700);
const y2 = Phaser.Math.Between(50, 550);
const x3 = Phaser.Math.Between(100, 700);
const y3 = Phaser.Math.Between(50, 550);
const triangle = new Phaser.Geom.Triangle(x1, y1, x2, y2, x3, y3);
После создания объекта треугольника, его можно отрисовать с помощью Graphics API.
const graphics = this.add.graphics({ lineStyle: { width: 2, color: 0x00ff00 } });
graphics.strokeTriangleShape(triangle);
Вычисляем инцентр
Phaser предоставляет статический метод Phaser.Geom.Triangle.InCenter(). Он принимает объект треугольника в качестве единственного аргумента и возвращает объект точки (Phaser.Geom.Point) с координатами `xиy`.
const incenter = Phaser.Geom.Triangle.InCenter(triangle);
После этого вызова в переменной incenter хранятся точные координаты искомого центра. Это готовая точка для дальнейшего использования в логике игры.
Визуализируем результат
Чтобы наглядно убедиться, что точка найдена верно, нарисуем линии от вершин треугольника к инцентру и выделим саму точку.
Сначала меняем стиль линий и рисуем отрезки от каждой вершины до центра.
graphics.lineStyle(1, 0x00ff00);
graphics.lineBetween(x1, y1, incenter.x, incenter.y);
graphics.lineBetween(x2, y2, incenter.x, incenter.y);
graphics.lineBetween(x3, y3, incenter.x, incenter.y);
Затем меняем контекст заливки и рисуем саму точку инцентра.
graphics.fillStyle(0xffff00);
graphics.fillPointShape(incenter, 4);
Метод fillPointShape рисует закрашенный круг с центром в заданной точке. Второй аргумент (4) — это радиус точки в пикселях.
Практическое применение в игре
Как использовать этот расчёт в реальном проекте? Допустим, у вас есть зона в форме треугольника (например, безопасный сектор на карте). Вычислив её инцентр, вы можете разместить там важный объект — сундук, контрольную точку или NPC.
// Предположим, zoneTriangle — это Phaser.Geom.Triangle, описывающий зону
const safePoint = Phaser.Geom.Triangle.InCenter(zoneTriangle);
// Создаём спрайт объекта в найденной точке
this.physics.add.sprite(safePoint.x, safePoint.y, 'treasure');
Это гарантирует, что объект будет расположен геометрически центрально внутри области, а не в одном из её углов.
Что попробовать дальше
Метод Phaser.Geom.Triangle.InCenter() — это мощный и простой инструмент для точных пространственных расчётов. Он избавляет от необходимости писать сложную математику вручную. Для экспериментов попробуйте использовать инцентр в динамически меняющемся треугольнике (вершины которого движутся) или комбинируйте его с другими методами геометрии Phaser, например, для проверки, находится ли игрок ближе к центру зоны, чем к её границам.
