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

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

Версия 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(640, 480);
        const child = new Phaser.Structs.Size(420, 340, Phaser.Structs.Size.NONE, parent);

        child.setMin(320, 240);

        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.NONE. Это означает, что изначально не применяются никакие автоматические режимы подгонки (вроде FIT или ENVELOP), и мы будем управлять размером вручную.

const parent = new Phaser.Structs.Size(640, 480);
const child = new Phaser.Structs.Size(420, 340, Phaser.Structs.Size.NONE, parent);

Установка минимального предела

Ключевой метод в этом примере — setMin(). Он устанавливает минимально допустимые значения ширины и высоты для дочернего размера. После вызова этого метода любые попытки задать размер меньше указанного предела будут автоматически скорректированы. В нашем случае минимальный размер установлен в 320x240 пикселей.

child.setMin(320, 240);

Динамическое изменение и визуализация

Основная логика взаимодействия связана с обработкой движения указателя мыши. При каждом движении курсора размер дочернего объекта обновляется методом setSize(), куда передаются текущие координаты указателя. Затем вызывается функция draw(), которая очищает старое изображение и отрисовывает обновленные прямоугольники.

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

Функция draw() выполняет три действия: 1. Очищает графический объект debug и сдвигает начало координат для удобства отрисовки. 2. Рисует контур родительского прямоугольника и залитый дочерний прямоугольник с полупрозрачным зеленым цветом. 3. Обновляет текстовое поле актуальными значениями ширины, высоты и соотношения сторон дочернего размера.

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}`
    ]);
};

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

Сцена включается в конфигурацию игры стандартным образом. Важно отметить, что размер холста игры (800x600) не связан напрямую с логическими размерами наших прямоугольников — они отрисовываются внутри сцены со смещением.

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

const game = new Phaser.Game(config);

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

Класс Phaser.Structs.Size — это мощный инструмент для управления размерами объектов с поддержкой ограничений и привязок. Показанный пример демонстрирует, как легко задать минимальный предел и реагировать на пользовательский ввод. Для экспериментов попробуйте: 1. Добавить максимальный размер с помощью метода setMax(). 2. Использовать другие флаги инициализации, например Phaser.Structs.Size.FIT, чтобы увидеть автоматическую подгонку. 3. Применить этот механизм к реальным игровым объектам, например, для ограничения масштабирования спрайта.