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

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

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

Живой запуск

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

Исходный код


class Example extends Phaser.Scene
{
    create ()
    {
        //  Our ellipse is centered at 400x300 and is 600px wide by 300px tall
        const ellipse = new Phaser.Geom.Ellipse(400, 300, 600, 300);

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

        graphics.strokeEllipseShape(ellipse, 64);

        this.input.on('pointermove', pointer =>
        {
        
            ellipse.width = Math.abs(pointer.x - ellipse.x) * 2;
            ellipse.height = Math.abs(pointer.y - ellipse.y) * 2;

            graphics.clear();
            graphics.strokeEllipseShape(ellipse, 64);
        
        });
    }
}

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

const game = new Phaser.Game(config);

Создание базового эллипса

Вся работа начинается с создания объекта эллипса. Класс Phaser.Geom.Ellipse принимает четыре ключевых параметра: координаты центра по осям X и Y, а затем ширину и высоту фигуры.

const ellipse = new Phaser.Geom.Ellipse(400, 300, 600, 300);

Здесь мы создаем эллипс с центром в точке (400, 300). Его начальная ширина составляет 600 пикселей, а высота — 300. Чтобы увидеть фигуру на экране, необходимо ее нарисовать. Для этого используется объект Graphics.

const graphics = this.add.graphics({ lineStyle: { width: 2, color: 0x00ff00 } });
graphics.strokeEllipseShape(ellipse, 64);

Метод strokeEllipseShape принимает сам объект эллипса и второй параметр — segments. Он определяет, насколько гладкой будет кривая. Чем больше сегментов, тем более плавным будет эллипс, но это может сказаться на производительности. Значение 64 является хорошим балансом для визуального качества.

Обработка движения курсора

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

this.input.on('pointermove', pointer => {
    // Код обновления эллипса будет здесь
});

Внутри функции-обработчика мы получаем объект pointer, который содержит текущие координаты курсора (pointer.x и pointer.y). Именно эти данные мы будем использовать для пересчета геометрии.

Логика изменения размера

Ключевая идея в том, чтобы сделать ширину и высоту эллипса зависимыми от расстояния между его центром и текущим положением курсора. Поскольку ширина и высота — это полные размеры фигуры, расстояние умножается на 2.

ellipse.width = Math.abs(pointer.x - ellipse.x) * 2;
ellipse.height = Math.abs(pointer.y - ellipse.y) * 2;

Использование Math.abs() (модуля числа) гарантирует, что размеры всегда будут положительными, независимо от того, находится ли курсор слева или справа от центра. Без этого, если pointer.x был бы меньше ellipse.x, ширина стала бы отрицательной, что привело бы к некорректному отображению.

Очистка и перерисовка

Объект Graphics в Phaser рисует поверх всего, что было нарисовано ранее. Если просто нарисовать новый эллипс, старый никуда не денется, и мы увидим на экране все предыдущие кадры. Чтобы этого избежать, необходимо очистить холст перед каждой новой отрисовкой.

graphics.clear();
graphics.strokeEllipseShape(ellipse, 64);

Метод clear() удаляет все, что было нарисовано этим конкретным объектом graphics. После этого мы заново рисуем наш обновленный эллипс с новыми размерами. Этот цикл (событие -> обновление данных -> очистка -> отрисовка) является стандартным для динамической графики.

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

Вы научились создавать эллипс, который динамически меняет форму, следуя за курсором. Основная концепция — это обновление свойств геометрического объекта (width, height) в ответ на событие ввода и его последующая перерисовка. Для экспериментов попробуйте изменить логику: пусть эллипс не следует за курсором, а отталкивается от него, меняя прозрачность или цвет обводки в зависимости от скорости движения мыши. Или используйте этот принцип для управления размером хитбокса босса в игре.