О чем этот пример
Создание и динамическое изменение геометрических фигур — частая задача в игровой разработке, будь то зоны коллизий, области отрисовки или произвольные полигоны. В этом примере мы рассмотрим класс `Phaser.Geom.Polygon` и его метод `GetNumberArray`, который преобразует сложную структуру данных в простой массив чисел. Это полезно для передачи данных в другие системы, оптимизации или ручной отрисовки с помощью графического контекста. Мы создадим интерактивный многоугольник, вершины которого можно перемещать и добавлять в реальном времени.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
create ()
{
const graphics = this.add.graphics({ lineStyle: { width: 2, color: 0xaa6622 } });
const points = [
new Phaser.Math.Vector2(420, 280),
new Phaser.Math.Vector2(450, 250),
new Phaser.Math.Vector2(470, 300)
];
const polygon = new Phaser.Geom.Polygon(points);
this.input.on('pointermove', pointer =>
{
points[points.length - 1].copy(pointer);
polygon.setTo(points);
redraw();
});
this.input.on('pointerdown', pointer =>
{
points.push(points[points.length - 1].clone());
});
redraw();
function redraw ()
{
graphics.clear();
graphics.strokePoints(polygon.points, true);
graphics.lineStyle(2, 0x0000aa);
const numbers = Phaser.Geom.Polygon.GetNumberArray(polygon);
graphics.beginPath();
// draw as if x was y and y was x
graphics.moveTo(numbers[1], numbers[0]);
for (let i = 0; i < numbers.length; i += 2)
{
graphics.lineTo(numbers[i + 1], numbers[i]);
}
graphics.lineTo(numbers[1], numbers[0]);
graphics.closePath();
graphics.strokePath();
}
}
}
const config = {
width: 800,
height: 600,
type: Phaser.AUTO,
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Создание полигона из векторов
В основе примера лежит класс Phaser.Geom.Polygon. Он принимает массив точек для создания фигуры. Каждая точка — это экземпляр Phaser.Math.Vector2, что удобно для математических операций.
Инициализируем массив точек и создаём полигон.
const points = [
new Phaser.Math.Vector2(420, 280),
new Phaser.Math.Vector2(450, 250),
new Phaser.Math.Vector2(470, 300)
];
const polygon = new Phaser.Geom.Polygon(points);
Динамическое обновление вершин
Чтобы сделать полигон интерактивным, мы навешиваем обработчики событий ввода. При движении указателя (pointermove) последняя вершина массива points копирует координаты курсора, а затем полигон полностью перестраивается методом setTo. При клике (pointerdown) в массив добавляется копия последней вершины, позволяя "зафиксировать" текущее положение и начать рисовать новую вершину с той же позиции.
this.input.on('pointermove', pointer => {
points[points.length - 1].copy(pointer);
polygon.setTo(points);
redraw();
});
this.input.on('pointerdown', pointer => {
points.push(points[points.length - 1].clone());
});
Преобразование в массив чисел
Ключевой метод в этом примере — Phaser.Geom.Polygon.GetNumberArray. Он извлекает все координаты вершин полигона и возвращает их в виде плоского одномерного массива чисел вида [x1, y1, x2, y2, ...]. Это низкоуровневое представление удобно для ручной передачи в другие API или для нестандартных операций с графикой.
Получаем массив и готовимся к отрисовке.
const numbers = Phaser.Geom.Polygon.GetNumberArray(polygon);
Отрисовка с инверсией координат
В примере происходит визуальная демонстрация работы с массивом numbers. Используя графический контекст (graphics), мы рисуем исходный полигон через strokePoints. Затем, для наглядности, рисуем второй контур, но с инверсией координат X и Y: берём numbers[i + 1] как X, а numbers[i] как Y. Это создаёт зеркальный эффект и показывает гибкость ручной работы с массивом.
Функция перерисовки очищает canvas и создаёт два контура.
function redraw ()
{
graphics.clear();
graphics.strokePoints(polygon.points, true);
graphics.lineStyle(2, 0x0000aa);
const numbers = Phaser.Geom.Polygon.GetNumberArray(polygon);
graphics.beginPath();
graphics.moveTo(numbers[1], numbers[0]);
for (let i = 0; i < numbers.length; i += 2)
{
graphics.lineTo(numbers[i + 1], numbers[i]);
}
graphics.lineTo(numbers[1], numbers[0]);
graphics.closePath();
graphics.strokePath();
}
Что попробовать дальше
Метод GetNumberArray — это мост между высокоуровневым объектом Polygon и низкоуровневыми данными. Он полезен для сериализации фигур, передачи в WebGL-шейдеры или создания кастомных алгоритмов обработки. Для экспериментов попробуйте: сохранять массив numbers в localStorage, анимировать вершины через Tween, или использовать его для расчёта площади полигона. Инверсия координат в отрисовке — лишь один пример манипуляций с таким массивом.
