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

В игровом движке Phaser часто требуется реализовать движение объектов по сложным траекториям. Метод `getPoint` класса `Phaser.Geom.Ellipse` позволяет получить координаты точки на эллипсе для заданного значения параметра. Это полезно для создания орбитального движения планет, циклических анимаций или плавного перемещения камеры по заданному пути без написания сложных математических расчетов вручную.

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

Живой запуск

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

Исходный код


class Example extends Phaser.Scene
{
    a = 0;
    point;
    ellipse;
    graphics;

    create ()
    {
        this.graphics = this.add.graphics({ lineStyle: { width: 2, color: 0x00ff00 }, fillStyle: { color: 0xff0000 }});

        this.ellipse = new Phaser.Geom.Ellipse(400, 300, 600, 300);
        this.point = new Phaser.Geom.Rectangle(0, 0, 16, 16);
    }

    update ()
    {
        this.a += 0.005;

        if (this.a > 1)
        {
            this.a = 0;
        }

        this.ellipse.getPoint(this.a, this.point);

        this.graphics.clear();
        this.graphics.lineStyle(2, 0x00ff00);
        this.graphics.strokeEllipseShape(this.ellipse, 64);

        this.graphics.fillStyle(0xff00ff);
        this.graphics.fillRect(this.point.x - 8, this.point.y - 8, this.point.width, this.point.height);
    }
}

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

const game = new Phaser.Game(config);

Инициализация геометрических объектов

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

this.graphics = this.add.graphics({ lineStyle: { width: 2, color: 0x00ff00 }, fillStyle: { color: 0xff0000 }});
this.ellipse = new Phaser.Geom.Ellipse(400, 300, 600, 300);
this.point = new Phaser.Geom.Rectangle(0, 0, 16, 16);

Работа метода getPoint

Ключевой метод getPoint принимает два аргумента: значение позиции на эллипсе (от 0 до 1) и объект, в который будут записаны координаты точки. Значение 0 соответствует крайней правой точке эллипса, 0.5 — крайней левой, а 1 снова возвращает нас в начальную позицию, обеспечивая непрерывное движение.

this.ellipse.getPoint(this.a, this.point);

В данном примере переменная this.a инкрементируется каждый кадр, обеспечивая плавное изменение позиции точки на эллипсе. Когда значение достигает 1, оно сбрасывается в 0, создавая зацикленную анимацию.

Визуализация в методе update

Каждый кадр происходит обновление позиции точки, очистка графики и перерисовка эллипса с точкой. Это стандартный подход для динамической графики в Phaser.

this.graphics.clear();
this.graphics.lineStyle(2, 0x00ff00);
this.graphics.strokeEllipseShape(this.ellipse, 64);

this.graphics.fillStyle(0xff00ff);
this.graphics.fillRect(this.point.x - 8, this.point.y - 8, this.point.width, this.point.height);

Обратите внимание на смещение координат при отрисовке прямоугольника: вычитание половины его размеров центрирует точку относительно рассчитанной позиции на эллипсе.

Конфигурация игры

Сцена интегрируется в игровой объект через стандартную конфигурацию Phaser. Размеры холста 800x600 пикселей соответствуют размерам созданного эллипса.

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

const game = new Phaser.Game(config);

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

Метод getPoint для работы с эллипсами — это мощный инструмент для создания предсказуемых и плавных траекторий движения. Для экспериментов попробуйте изменить скорость инкремента переменной this.a, чтобы ускорить или замедлить движение. Можно привязать не прямоугольник, а спрайт игрока или врага к этой точке, создав орбитальное движение вокруг центра. Также интересно поэкспериментировать с изменением размеров эллипса во время выполнения, чтобы получить динамическую траекторию.