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

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

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

Живой запуск

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

Исходный код


class Example extends Phaser.Scene
{
    graphics;
    image1;

    preload ()
    {
        this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
        this.load.image('logo', 'assets/sprites/phaser3-logo.png');
    }

    create ()
    {
        this.image1 = this.add.image(400, 300, 'logo');

        this.image1.setScale(0.5);

        this.tweens.add({

            targets: this.image1,
            duration: 2000,
            scaleX: 2,
            scaleY: 4,
            ease: 'Sine.easeInOut',
            repeat: -1,
            yoyo: true

        });

        this.graphics = this.add.graphics();
    }

    update ()
    {
        this.graphics.clear();

        const topLeft = this.image1.getTopLeft();

        this.graphics.fillStyle(0x00ff00, 1);
        this.graphics.fillRect(topLeft.x, topLeft.y, 6, 6);

        const topCenter = this.image1.getTopCenter();

        this.graphics.fillStyle(0xf0ff0f, 1);
        this.graphics.fillRect(topCenter.x, topCenter.y, 6, 6);

        const topRight = this.image1.getTopRight();

        this.graphics.fillStyle(0xff0000, 1);
        this.graphics.fillRect(topRight.x, topRight.y, 6, 6);

        const leftCenter = this.image1.getLeftCenter();

        this.graphics.fillStyle(0xff00ff, 1);
        this.graphics.fillRect(leftCenter.x, leftCenter.y, 6, 6);

        const rightCenter = this.image1.getRightCenter();

        this.graphics.fillStyle(0x00ff00, 1);
        this.graphics.fillRect(rightCenter.x, rightCenter.y, 6, 6);

        const bottomLeft = this.image1.getBottomLeft();

        this.graphics.fillStyle(0xff00ff, 1);
        this.graphics.fillRect(bottomLeft.x, bottomLeft.y, 6, 6);

        const bottomCenter = this.image1.getBottomCenter();

        this.graphics.fillStyle(0x00fff0, 1);
        this.graphics.fillRect(bottomCenter.x, bottomCenter.y, 6, 6);

        const bottomRight = this.image1.getBottomRight();

        this.graphics.fillStyle(0x0000ff, 1);
        this.graphics.fillRect(bottomRight.x, bottomRight.y, 6, 6);

        this.image1.rotation += 0.013;
    }
}

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

const game = new Phaser.Game(config);

Загрузка и создание изображения с анимацией

В начале сцены мы загружаем спрайт логотипа Phaser. В методе create() создаем изображение и сразу применяем к нему начальный масштаб 0.5. Затем добавляем твин, который плавно меняет масштаб изображения по осям X и Y с повтором и эффектом йо-йо. Это создает постоянную анимацию, изменяющую размеры объекта, что важно для демонстрации работы методов получения точек.

this.image1 = this.add.image(400, 300, 'logo');
this.image1.setScale(0.5);

this.tweens.add({
    targets: this.image1,
    duration: 2000,
    scaleX: 2,
    scaleY: 4,
    ease: 'Sine.easeInOut',
    repeat: -1,
    yoyo: true
});

Создание графического контекста для отладки

Чтобы визуализировать крайние точки изображения, мы используем графический объект Graphics. Он создается один раз в create() и будет переиспользоваться в каждом кадре для рисования маркеров. В начале метода update() мы вызываем clear(), чтобы стереть маркеры предыдущего кадра, так как изображение движется и поворачивается.

this.graphics = this.add.graphics();

// В update()
this.graphics.clear();

Получение крайних точек изображения

Phaser предоставляет набор методов для получения мировых координат ключевых точек изображения. Каждый метод возвращает объект Phaser.Math.Vector2 с координатами x и y. В примере мы получаем восемь точек: три верхние (левый, центр, правый край), две боковые (центр слева и справа) и три нижние. Эти координаты учитывают текущие трансформации объекта: позицию, масштаб, вращение и происхождение (origin).

const topLeft = this.image1.getTopLeft();
const topCenter = this.image1.getTopCenter();
const topRight = this.image1.getTopRight();
const leftCenter = this.image1.getLeftCenter();
const rightCenter = this.image1.getRightCenter();
const bottomLeft = this.image1.getBottomLeft();
const bottomCenter = this.image1.getBottomCenter();
const bottomRight = this.image1.getBottomRight();

Визуализация точек и вращение изображения

Для каждой полученной точки мы задаем уникальный цвет через fillStyle() и рисуем маленький квадрат размером 6x6 пикселей с помощью fillRect(). Это позволяет наглядно увидеть, как точки перемещаются в пространстве при изменении масштаба и вращении. В конце update() мы добавляем инкремент к свойству rotation изображения, заставляя его непрерывно вращаться. Это демонстрирует, что методы корректно работают даже с вращающимися объектами.

this.graphics.fillStyle(0x00ff00, 1);
this.graphics.fillRect(topLeft.x, topLeft.y, 6, 6);

// ... аналогично для других точек

this.image1.rotation += 0.013;

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

Эти методы крайне полезны в реальных проектах. Например, getBottomCenter() можно использовать для точного позиционирования тени под персонажем. getLeftCenter() и getRightCenter() пригодятся для определения точек выхода снарядов из дула оружия, прикрепленного к спрайту. Методы getTopLeft() и getBottomRight() часто используются для расчета ограничивающего прямоугольника (bounding box) при проверке столкновений "по грубой силе" или для отрисовки дебаг-контура. Важно помнить, что координаты возвращаются в мировом пространстве сцены, а не в локальных координатах объекта.

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

Использование методов для получения крайних точек изображения в Phaser 3 — это мощный инструмент для точного позиционирования, обработки столкновений и создания визуальных эффектов, которые зависят от границ объекта. Для экспериментов попробуйте изменить происхождение (origin) изображения с помощью setOrigin() и понаблюдайте, как смещаются точки. Или используйте полученные координаты для привязки других игровых объектов, например, частиц, которые будут следовать за углами движущегося спрайта.