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

Интерактивная геометрия — основа игровой механики, от расчёта траекторий до построения интерфейсов. В этом примере мы создадим инструмент для рисования линии мышью и мгновенно "перевернём" её на 180 градусов. Этот приём полезен для создания симметричных построений, отражения объектов или реализации механики зеркального отражения. Вы научитесь работать с линиями, обрабатывать ввод и применять геометрические преобразования в реальном времени.

Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.

Живой запуск

Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.

Исходный код


class Example extends Phaser.Scene
{
    create ()
    {
        const graphics = this.add.graphics();

        const line = new Phaser.Geom.Line();

        this.input.on('pointerdown', pointer =>
        {

            line.setTo(pointer.x, pointer.y, pointer.x, pointer.y);

            graphics.clear();
            graphics.lineStyle(4, 0xaa00aa);
            graphics.strokeLineShape(line);

        });

        this.input.on('pointermove', pointer =>
        {

            if (pointer.isDown)
            {
                line.x2 = pointer.x;
                line.y2 = pointer.y;
        
                graphics.clear();
                graphics.lineStyle(4, 0xaa00aa);
                graphics.strokeLineShape(line);
            }

        });

        this.input.on('pointerup', pointer =>
        {

            Phaser.Geom.Line.RotateAroundPoint(line, line.getPointA(), Math.PI);

            graphics.clear();
            graphics.lineStyle(4, 0x00ff00);
            graphics.strokeLineShape(line);

        });
    }
}

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

const game = new Phaser.Game(config);

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

В Phaser работа с графикой начинается с создания объекта Graphics. Это наш виртуальный холст, на котором мы будем рисовать фигуры. Также мы создаём пустой объект линии класса Phaser.Geom.Line. Изначально у него нет координат. Этот объект будет хранить данные о нашей линии, а Graphics — отображать её.

const graphics = this.add.graphics();
const line = new Phaser.Geom.Line();

Начало рисования при клике

Мы хотим, чтобы линия начинала рисоваться с момента нажатия кнопки мыши. Для этого используем событие pointerdown. Когда пользователь кликает, мы устанавливаем начальную точку линии (A) и конечную точку (B) в одно и то же место — координаты клика. Затем очищаем холст и рисуем линию с заданным стилем.

this.input.on('pointerdown', pointer => {
    line.setTo(pointer.x, pointer.y, pointer.x, pointer.y);
    graphics.clear();
    graphics.lineStyle(4, 0xaa00aa);
    graphics.strokeLineShape(line);
});

Динамическое изменение линии при перетаскивании

Пока кнопка мыши зажата, мы отслеживаем её движение. При событии pointermove проверяем, нажата ли кнопка (pointer.isDown). Если да, то обновляем только конечную точку линии (B), присваивая ей текущие координаты курсора. Линия начинает растягиваться от точки клика до курсора. Холст очищается и линия перерисовывается каждый кадр, создавая эффект плавного рисования.

this.input.on('pointermove', pointer => {
    if (pointer.isDown) {
        line.x2 = pointer.x;
        line.y2 = pointer.y;
        graphics.clear();
        graphics.lineStyle(4, 0xaa00aa);
        graphics.strokeLineShape(line);
    }
});

Магия поворота при отпускании кнопки

Самое интересное происходит, когда пользователь отпускает кнопку мыши. Мы используем статический метод Phaser.Geom.Line.RotateAroundPoint. Этот метод вращает линию вокруг заданной точки на указанный угол в радианах. В нашем случае мы вращаем линию вокруг её начальной точки (получаемой методом line.getPointA()) на угол π (180 градусов). После поворота линия перерисовывается зелёным цветом, визуально показывая результат преобразования.

this.input.on('pointerup', pointer => {
    Phaser.Geom.Line.RotateAroundPoint(line, line.getPointA(), Math.PI);
    graphics.clear();
    graphics.lineStyle(4, 0x00ff00);
    graphics.strokeLineShape(line);
});

Конфигурация и запуск игры

Код завершается стандартной конфигурацией игры Phaser. Мы задаём размеры окна, указываем тип рендерера (Phaser.AUTO выбирает WebGL или Canvas автоматически) и передаём наш класс сцены. Создание экземпляра Phaser.Game с этой конфигурацией запускает приложение.

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

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

Вы создали интерактивный инструмент для рисования и мгновенного поворота линии. Это основа для более сложных манипуляций с геометрией. Попробуйте изменить угол поворота или точку вращения. Например, вращение вокруг центра линии (line.getMidPoint()). Экспериментируйте с другими методами, такими как Phaser.Geom.Line.Reflect для зеркального отражения, чтобы создавать симметричные уровни или траектории снарядов.