О чем этот пример
При разработке игр часто требуется найти центр сложной фигуры или группы объектов для расчёта ударов, создания эффектов или AI. Встроенная функция `Phaser.Math.GetCentroid` мгновенно вычисляет геометрический центр (центроид) любого набора точек. Это избавляет от написания сложных математических расчётов и позволяет сосредоточиться на игровой логике. В этой статье мы разберём практический пример и покажем, как центроид может оживить вашу игру.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
create ()
{
const graphics = this.add.graphics({ lineStyle: { width: 2, color: 0x2266aa }, fillStyle: { color: 0x2266aa } });
const points = [
new Phaser.Math.Vector2(Math.random() * 300, Math.random() * 200),
new Phaser.Math.Vector2(Math.random() * 400 + 400, Math.random() * 200),
new Phaser.Math.Vector2(Math.random() * 400 + 400, Math.random() * 200 + 200),
new Phaser.Math.Vector2(Math.random() * 400, Math.random() * 300 + 300),
new Phaser.Math.Vector2(Math.random() * 400, Math.random() * 300 + 300)
];
this.input.on('pointermove', pointer =>
{
points[0].copy(pointer);
redraw();
});
redraw();
function redraw ()
{
graphics.clear();
graphics.strokePoints(points, true);
const centroid = Phaser.Math.GetCentroid(points);
graphics.fillPointShape(centroid, 20);
graphics.lineStyle(1, 0x2266aa);
for (let i = 0; i < points.length; i++)
{
graphics.lineBetween(points[i].x, points[i].y, centroid.x, centroid.y);
}
}
}
}
const config = {
width: 800,
height: 600,
type: Phaser.AUTO,
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Что такое центроид и зачем он нужен?
Центроид — это средняя арифметическая позиция всех точек фигуры. Представьте, что вы размещаете одинаковые гирьки в каждой вершине многоугольника: точка, где эта конструкция будет балансировать, и есть центроид.
В играх центроид полезен для: - Определения центра массы объекта для реалистичной физики. - Привязки эффектов (взрыв, свечение) к центру группы спрайтов. - Нахождения усреднённой позиции для камеры или AI, следящей за несколькими целями.
Phaser предоставляет для этого готовую функцию Phaser.Math.GetCentroid, которая работает с массивом объектов Vector2.
Анализ примера: создание сцены и точек
Весь код выполняется внутри метода create сцены. Сначала создаётся объект graphics для рисования.
const graphics = this.add.graphics({ lineStyle: { width: 2, color: 0x2266aa }, fillStyle: { color: 0x2266aa } });
Затем определяется массив points, состоящий из пяти векторов (Phaser.Math.Vector2) со случайными координатами. Эти векторы представляют вершины нашей динамической фигуры.
const points = [
new Phaser.Math.Vector2(Math.random() * 300, Math.random() * 200),
new Phaser.Math.Vector2(Math.random() * 400 + 400, Math.random() * 200),
new Phaser.Math.Vector2(Math.random() * 400 + 400, Math.random() * 200 + 200),
new Phaser.Math.Vector2(Math.random() * 400, Math.random() * 300 + 300),
new Phaser.Math.Vector2(Math.random() * 400, Math.random() * 300 + 300)
];
Первая точка в массиве привязана к движению курсора мыши с помощью слушателя события pointermove. Это делает фигуру интерактивной.
this.input.on('pointermove', pointer =>
{
points[0].copy(pointer);
redraw();
});
Магия одного вызова: расчёт центроида
Ключевая логика заключена в функции redraw. После очистки холста (graphics.clear()) она рисует контур фигуры по точкам.
Затем всего одним вызовом вычисляется центроид:
const centroid = Phaser.Math.GetCentroid(points);
Функция принимает массив точек и возвращает новый объект Vector2 — координаты центроида. Это мощный инструмент, скрывающий за собой все математические операции.
Визуализация результата
Чтобы результат был наглядным, пример не просто вычисляет центроид, но и отрисовывает его вместе с "лучами", соединяющими его с вершинами.
Сначала центроид рисуется как закрашенная точка:
graphics.fillPointShape(centroid, 20);
Затем стиль линии меняется, и в цикле рисуются соединительные линии:
graphics.lineStyle(1, 0x2266aa);
for (let i = 0; i < points.length; i++)
{
graphics.lineBetween(points[i].x, points[i].y, centroid.x, centroid.y);
}
Такая визуализация помогает увидеть, как именно центроид связан с формой фигуры и как он перемещается при её изменении.
Практическое применение в играх
Вот несколько идей, как использовать центроид в реальном проекте:
1. **Групповой урон:** Если взрыв происходит в центроиде группы врагов, урон можно распределить правдоподобно.
// enemies - массив спрайтов с физическими телами
const positions = enemies.map(e => new Phaser.Math.Vector2(e.x, e.y));
const blastCenter = Phaser.Math.GetCentroid(positions);
this.physics.add.explosion(blastCenter.x, blastCenter.y, 200);
2. **Фокусировка камеры:** Плавное движение камеры к центру массы выбранных юнитов. 3. **Создание сложных траекторий:** Центроид нескольких контрольных точек может задавать путь для патрулирования или красивых закруглённых движений.
Главное преимущество — не нужно вручную суммировать и делить координаты. Phaser делает это за вас.
Что попробовать дальше
Функция Phaser.Math.GetCentroid — это небольшой, но мощный инструмент для работы с геометрией в играх. Она мгновенно решает задачу нахождения центра, позволяя создавать более умные и визуально интересные механики.
Поэкспериментируйте: привяжите центроид не к курсору, а к движущемуся спрайту-лидеру, используйте его для расчёта силы притяжения или создайте динамический интерфейс, который всегда указывает на центр группы выбранных объектов.
