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

При создании интерфейсов или UI-элементов в играх часто требуется, чтобы дочерний блок менял свои размеры, сохраняя пропорции относительно родительского контейнера. Класс `Phaser.Structs.Size` предоставляет мощный инструмент для управления размерами с заданным режимом соотношения сторон. В этой статье мы разберем, как использовать режим `WIDTH_CONTROLS_HEIGHT`, при котором высота вычисляется автоматически на основе установленной ширины и исходного соотношения сторон. Это полезно для создания адаптивных элементов интерфейса, которые должны вписываться в заданную область.

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

Живой запуск

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

Исходный код


class Example extends Phaser.Scene
{
    create ()
    {
        const debug = this.add.graphics();
        const text = this.add.text(10, 540, '', { fill: '#00ff00' });

        const parent = new Phaser.Structs.Size(400, 300);
        const child = new Phaser.Structs.Size(300, 200, Phaser.Structs.Size.WIDTH_CONTROLS_HEIGHT, parent);

        const draw = () =>
        {
            debug.clear().translateCanvas(10, 10);
            debug.lineStyle(1.5, 0xffff00).strokeRect(1, 1, parent.width, parent.height);
            debug.fillStyle(0x00ff00, 0.5).fillRect(1, 1, child.width, child.height);

            text.setText([
                `width: ${child.width}`,
                `height: ${child.height}`,
                `aspect ratio: ${child.aspectRatio}`
            ]);
        };

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

            child.setSize(pointer.x, pointer.y);

            draw();

        });

        draw();
    }
}

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

const game = new Phaser.Game(config);

Создание родительского и дочернего размеров

В начале примера создаются два объекта Phaser.Structs.Size: родительский (parent) и дочерний (child). Родительский размер задает границы, в которых будет находиться дочерний элемент. Дочерний размер создается с указанием режима Phaser.Structs.Size.WIDTH_CONTROLS_HEIGHT и ссылкой на родительский объект. Это означает, что при изменении ширины дочернего элемента его высота будет пересчитана автоматически, чтобы сохранить исходное соотношение сторон (aspect ratio), вычисленное из начальных ширины и высоты (300x200).

const parent = new Phaser.Structs.Size(400, 300);
const child = new Phaser.Structs.Size(300, 200, Phaser.Structs.Size.WIDTH_CONTROLS_HEIGHT, parent);

Визуализация и функция отрисовки

Для наглядности создается графический объект debug и текстовый объект text. Функция draw() отвечает за отрисовку прямоугольников, представляющих родительскую и дочернюю области, и обновление текстовой информации. Родительский прямоугольник рисуется желтой рамкой с помощью strokeRect, а дочерний — полупрозрачной зеленой заливкой с помощью fillRect. Текст выводит текущую ширину, высоту и соотношение сторон дочернего элемента.

const draw = () =>
{
    debug.clear().translateCanvas(10, 10);
    debug.lineStyle(1.5, 0xffff00).strokeRect(1, 1, parent.width, parent.height);
    debug.fillStyle(0x00ff00, 0.5).fillRect(1, 1, child.width, child.height);

    text.setText([
        `width: ${child.width}`,
        `height: ${child.height}`,
        `aspect ratio: ${child.aspectRatio}`
    ]);
};

Обработка ввода и обновление размера

Сцена подписывается на событие движения указателя pointermove. При каждом движении мыши координаты указателя (pointer.x, pointer.y) передаются в метод child.setSize(). Важно понимать, что, несмотря на передачу двух аргументов, в режиме WIDTH_CONTROLS_HEIGHT только ширина (pointer.x) будет использована для установки нового размера. Высота будет вычислена автоматически на основе переданной ширины и исходного соотношения сторон дочернего элемента. После обновления размера вызывается draw() для перерисовки.

this.input.on('pointermove', pointer =>
{
    child.setSize(pointer.x, pointer.y);
    draw();
});

Конфигурация игры и запуск

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

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

const game = new Phaser.Game(config);

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

Класс Phaser.Structs.Size с режимом WIDTH_CONTROLS_HEIGHT позволяет легко создавать элементы, которые динамически меняют размер, сохраняя пропорции. Это особенно полезно для UI-компонентов, например, кнопок с иконками или панелей с фоновым изображением. Для экспериментов попробуйте изменить режим на HEIGHT_CONTROLS_WIDTH или использовать метод setAspectRatio для динамического изменения соотношения сторон во время выполнения.