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

Расчёт нормали к линии — базовая, но мощная операция в игровой геометрии. Она позволяет получить перпендикуляр к отрезку, что критически важно для расчёта отскоков, определения направления движения вдоль стен, создания векторных эффектов и реализации простой 2D физики. В этой статье мы разберём пример из официальной документации Phaser, покажем, как работает `Phaser.Geom.Line.NormalAngle`, и объясним практическое применение этого метода в реальных игровых проектах.

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

Живой запуск

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

Исходный код


class Example extends Phaser.Scene
{
    create ()
    {

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

        const line = new Phaser.Geom.Line(400, 300, 550, 300);

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

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

            line.x2 = pointer.x;
            line.y2 = pointer.y;

            redraw();
        });

        redraw();

        function redraw ()
        {
            graphics.clear();

            graphics.strokeLineShape(line);

            const normalAngle = Phaser.Geom.Line.NormalAngle(line);

            graphics.lineStyle(2, 0x00aa00);
            graphics.lineBetween(400, 300, 400 + Math.cos(normalAngle) * 100, 300 + Math.sin(normalAngle) * 100);

            text.setText(`Line Normal Angle: ${Phaser.Math.RadToDeg(normalAngle)}`);
        }
    }
}

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

const game = new Phaser.Game(config);

Что такое нормаль к линии и зачем она нужна

Нормаль к линии — это вектор, перпендикулярный ей. В 2D-пространстве для любого отрезка существует два таких направления (влево и вправо от него). Нормаль используется повсеместно: от простого вычисления угла отражения снаряда от стены до определения, с какой стороны от препятствия находится игрок.

В контексте Phaser, метод Phaser.Geom.Line.NormalAngle(line) возвращает не сам вектор, а его угол в радианах. Это базовая, но точная информация, которую затем можно использовать для создания вектора направления или немедленного применения в графике и физике.

Разбор примера: Интерактивная визуализация

Исходный код создаёт сцену с линией, один конец которой закреплён, а второй следует за курсором мыши. В реальном времени вычисляется и отрисовывается нормаль.

Сначала создаются необходимые объекты: графический контейнер (graphics) для рисования, геометрическая линия (line) и текстовое поле (text) для вывода угла.

const graphics = this.add.graphics({ lineStyle: { width: 4, color: 0xaa00aa } });
const line = new Phaser.Geom.Line(400, 300, 550, 300);
const text = this.add.text(50, 50, '');

Слушатель события движения мыши обновляет конечную точку линии и вызывает функцию перерисовки.

this.input.on('pointermove', pointer => {
    line.x2 = pointer.x;
    line.y2 = pointer.y;
    redraw();
});

Ядро примера: Функция redraw() и метод NormalAngle

Вся магия происходит в функции redraw(). После очистки холста она рисует саму линию.

graphics.clear();
graphics.strokeLineShape(line);

Затем вычисляется угол нормали. Это ключевой вызов.

const normalAngle = Phaser.Geom.Line.NormalAngle(line);

Полученный угол в радианах используется для отрисовки перпендикуляра. Мы вычисляем конечную точку для отрезка длиной 100 пикселей, используя тригонометрические функции Math.cos и Math.sin.

graphics.lineStyle(2, 0x00aa00);
graphics.lineBetween(400, 300,
                     400 + Math.cos(normalAngle) * 100,
                     300 + Math.sin(normalAngle) * 100);

Наконец, угол конвертируется в градусы (для удобства чтения) и выводится на экран.

text.setText(`Line Normal Angle: ${Phaser.Math.RadToDeg(normalAngle)}`);

Практическое применение в играх

1. **Физика отскока (Bouncing):** Чтобы отразить вектор скорости объекта от линии (стены), вам нужна её нормаль. По формуле отражения вы сможете рассчитать новый направляющий вектор. 2. **Скольжение вдоль поверхности:** Если персонаж движется вдоль стены, его направление часто корректируется проекцией вектора скорости на нормаль, чтобы не "залипать". 3. **Определение стороны:** Сравнив нормаль с вектором "от объекта к точке", можно определить, находится ли точка слева или справа от отрезка. Это полезно для AI и геометрических тестов. 4. **Генерация смещений:** Нормаль — это идеальное направление для смещения параллельных линий, создания контуров или эффектов "выдавливания" (extrude) для 2D-графики.

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

Метод Phaser.Geom.Line.NormalAngle предоставляет простой и эффективный способ получить перпендикулярное направление к отрезку, открывая дверь к реализации реалистичной 2D-физики и геометрических механик. **Идеи для экспериментов:** 1. Модифицируйте пример, чтобы нормаль отрисовывалась из середины отрезка, а не из его начала. 2. Создайте сцену с несколькими статичными линиями-стенами и шариком, который от них реалистично отскакивает, используя рассчитанную нормаль для изменения его скорости. 3. Используйте нормаль для создания эффекта "свечения" или тени, отбрасываемой от линии в перпендикулярном направлении.