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

В игровой разработке часто нужно знать расстояние от точки до начала координат или длину вектора. Например, для определения силы удара, дальности видимости врага или интенсивности свечения. Phaser предоставляет для этого простой, но мощный инструмент — метод `length()` (или `magnitude()`) у объектов `Vector2`. Эта статья на практическом примере покажет, как легко и эффективно рассчитывать длину вектора и визуализировать результат, что станет основой для многих игровых механик.

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

Живой запуск

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

Исходный код


class Example extends Phaser.Scene
{
    create ()
    {

        const graphics = this.add.graphics({ lineStyle: { width: 1, color: 0x2266aa }, fillStyle: { color: 0x2266aa } });

        const point = new Phaser.Math.Vector2(400, 300);

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

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

            point.copy(pointer);

            redraw();
        });

        redraw();

        function redraw ()
        {
            graphics.clear();

            graphics.fillPointShape(point, 20);

            graphics.lineBetween(0, 0, point.x, point.y);

            const magnitude = point.length();

            text.setText(`Point Magnitude: ${magnitude}`);
        }
    }
}

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

const game = new Phaser.Game(config);

Что такое длина вектора?

В контексте 2D-графики вектор можно представить как стрелку, идущую из начала координат (точки 0,0) до заданной точки (x, y). Длина (или модуль) этого вектора — это расстояние по прямой от начала координат до этой точки.

Рассчитывается она по теореме Пифагора: квадратный корень из суммы квадратов координат (x² + y²). В Phaser вам не нужно вспоминать школьную геометрию — встроенный метод Vector2.length() сделает всё за вас.

В предоставленном примере точка point является вектором от начала координат (верхний левый угол холста) до позиции курсора. Метод point.length() возвращает её длину.

Разбираем исходный код

Давайте последовательно разберем ключевые части примера, чтобы понять, как всё работает.

Создается вектор point, который будет хранить текущие координаты. Изначально он установлен в центр экрана.

const point = new Phaser.Math.Vector2(400, 300);

При движении указателя мыши его координаты копируются в наш вектор point с помощью метода copy(), и вызывается функция перерисовки redraw().

this.input.on('pointermove', pointer => {
    point.copy(pointer);
    redraw();
});

Функция redraw() — это сердце примера. Она очищает старое изображение, рисует точку и линию от начала координат, а затем вычисляет и отображает длину вектора.

function redraw() {
    graphics.clear();
    graphics.fillPointShape(point, 20);
    graphics.lineBetween(0, 0, point.x, point.y);
    const magnitude = point.length();
    text.setText(`Point Magnitude: ${magnitude}`);
}

Вот что делает каждая строка внутри redraw(): 1. graphics.clear() — стирает все, что было нарисовано объектом graphics в предыдущем кадре. 2. graphics.fillPointShape(point, 20) — рисует закрашенный круг (точку) в позиции вектора point с радиусом 20 пикселей. 3. graphics.lineBetween(0, 0, point.x, point.y) — рисует линию из начала координат (0,0) до позиции точки, визуализируя сам вектор. 4. const magnitude = point.length() — ключевой вызов! Здесь вычисляется длина вектора point и сохраняется в переменную magnitude. 5. text.setText(...) — обновляет текстовый объект, выводя рассчитанное значение на экран.

Ключевой метод Vector2.length()

Метод length() объекта Phaser.Math.Vector2 возвращает евклидову длину (модуль) вектора. Это скалярная величина (просто число), которая всегда неотрицательна.

const myVector = new Phaser.Math.Vector2(3, 4);
const len = myVector.length(); // len = 5

В этом примере вектор (3,4) имеет длину 5 (по теореме Пифагора: √(3² + 4²) = √25 = 5).

Phaser также предоставляет метод-синоним magnitude(), который делает абсолютно то же самое. Вы можете использовать тот, который кажется вам более интуитивным в контексте вашей игры.

const lenAlso = myVector.magnitude(); // lenAlso = 5

Важно помнить, что вычисление квадратного корня — относительно затратная операция. Если вам нужно просто сравнить длины (например, проверить, находится ли объект в радиусе действия), эффективнее использовать метод lengthSq(), который возвращает квадрат длины, избегая вычисления корня.

const radius = 100;
const radiusSquared = radius * radius;
const distanceSquared = point.lengthSq();

if (distanceSquared < radiusSquared) {
    // Точка находится внутри круга с радиусом 100
}

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

Расчет длины вектора — фундаментальная операция для множества игровых механик.

* **Определение дистанции:** Самый очевидный случай — расчет расстояния между двумя точками. Для этого нужно создать вектор разности между ними и найти его длину.

const player = new Phaser.Math.Vector2(100, 200);
    const enemy = new Phaser.Math.Vector2(400, 150);
    
    // Создаем вектор, направленный от игрока к врагу
    const distanceVector = new Phaser.Math.Vector2(enemy.x - player.x, enemy.y - player.y);
    const distance = distanceVector.length(); // Дистанция между объектами

* **ИИ врагов:** Враг может «увидеть» игрока, только если тот находится в пределах определенного радиуса (дальности видимости). * **Сила воздействия:** В физических играх длина вектора скорости (body.velocity) может определять силу столкновения или урона. * **Нормализация векторов:** Чтобы получить вектор направления единичной длины (важно для равномерного движения), нужно разделить исходный вектор на его длину: vector.normalize(). Внутри себя этот метод как раз использует length().

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

Метод Vector2.length() — это ваш надежный инструмент для работы с расстояниями и величинами в 2D-пространстве Phaser. Он абстрагирует математические вычисления, позволяя сосредоточиться на игровой логике. **Идеи для экспериментов:** 1. Создайте объект, который притягивается к курсору с силой, обратно пропорциональной расстоянию (чем ближе, тем сильнее притяжение). 2. Реализуйте «радар» или мини-карту, где объекты за пределами определенного радиуса от игрока не отображаются. 3. Модифицируйте пример, чтобы линия рисовалась не из угла (0,0), а из произвольной фиксированной точки на экране, и изучите, как меняется длина.