О чем этот пример

Работа с геометрией — основа для многих игровых механик: от столкновений до генерации уровней. В этом примере мы покажем, как использовать класс `Phaser.Geom.Polygon` для создания динамического многоугольника и расчета его площади в реальном времени. Этот подход полезен для создания редакторов уровней, проверки хитбоксов сложной формы или procedural generation.

Версия 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(220, 450),
            new Phaser.Math.Vector2(200, 200),
            new Phaser.Math.Vector2(400, 300)
        ];

        const polygon = new Phaser.Geom.Polygon(points);

        const text = this.add.text(400, 50, '');

        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);

            text.setText(`Polygon Area: ${polygon.area}`);
        }
    }
}

const config = {
    width: 800,
    height: 600,
    type: Phaser.AUTO,
    parent: 'phaser-example',
    scene: Example
};

const game = new Phaser.Game(config);

Создание полигона и подготовка сцены

В методе create() мы инициализируем основные объекты. Сначала создается объект graphics для отрисовки линий, который будет визуализировать наш полигон. Затем определяем массив точек points, которые станут вершинами многоугольника.

const graphics = this.add.graphics({ lineStyle: { width: 2, color: 0xaa6622 } });

const points = [
    new Phaser.Math.Vector2(220, 450),
    new Phaser.Math.Vector2(200, 200),
    new Phaser.Math.Vector2(400, 300)
];

const polygon = new Phaser.Geom.Polygon(points);

Эти точки передаются в конструктор Phaser.Geom.Polygon, создавая геометрический объект. Также создается текстовый объект text для вывода площади.

Обработка ввода для изменения формы

Чтобы полигон стал интерактивным, мы настраиваем обработчики событий мыши. При движении указателя (pointermove) последняя точка массива обновляет свои координаты, а полигон перестраивается с помощью метода setTo(). Затем вызывается функция redraw() для обновления изображения.

this.input.on('pointermove', pointer =>
{
    points[points.length - 1].copy(pointer);
    polygon.setTo(points);
    redraw();
});

При клике (pointerdown) в массив добавляется копия последней точки, позволяя создавать новые вершины. Это дает эффект "приклеивания" точки и начала рисования нового сегмента.

this.input.on('pointerdown', pointer =>
{
    points.push(points[points.length - 1].clone());
});

Визуализация и расчет площади

Функция redraw() отвечает за отрисовку и обновление информации. Сначала очищается холст graphics, затем метод strokePoints() рисует линии, соединяя точки полигона. Ключевой момент — получение площади через свойство polygon.area. Это встроенный расчет, который не требует дополнительной математики.

function redraw ()
{
    graphics.clear();
    graphics.strokePoints(polygon.points, true);
    text.setText(`Polygon Area: ${polygon.area}`);
}

Свойство area возвращает площадь в пикселях. Для простых полигонов это может быть положительное значение, для самопересекающихся — отрицательное, что полезно для определения ориентации вершин.

Что попробовать дальше

Использование Phaser.Geom.Polygon и его свойства area упрощает работу с геометрией в играх. Вы можете расширить этот пример: добавить проверку, попадает ли точка внутрь полигона (polygon.contains()), рассчитывать периметр или использовать площадь для балансировки игровых объектов (например, размер территории). Попробуйте интегрировать этот код в редактор карт для стратегической игры.