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

При разработке игр под разные устройства важно правильно управлять отображением игрового холста. Phaser предоставляет мощную систему масштабирования через объект `Scale Manager`. В этой статье мы разберем режим `ENVELOP` и настройку минимальных (`min`) и максимальных (`max`) размеров холста. Это позволит вашей игре сохранять пропорции и качество изображения на экранах с самым разным разрешением, от мобильных устройств до больших мониторов, без растягивания или обрезания критически важных областей.

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

Живой запуск

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

Исходный код


class Example extends Phaser.Scene
{
    preload ()
    {
        this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
        this.load.image('pic', 'assets/pics/zero-two.png');
    }

    create ()
    {
        this.add.image(0, 0, 'pic').setOrigin(0);
    }
}

const config = {
    type: Phaser.AUTO,
    backgroundColor: '#2dab2d',
    scale: {
        mode: Phaser.Scale.ENVELOP,
        parent: 'phaser-example',
        width: 800,
        height: 600,
        min: {
            width: 800,
            height: 600
        },
        max: {
            width: 1600,
            height: 1200
        }
    },
    scene: Example
};

const game = new Phaser.Game(config);

Что такое режим ENVELOP?

Режим Phaser.Scale.ENVELOP — это один из способов масштабирования игрового холста. Его логика проста: холст будет масштабироваться так, чтобы полностью поместиться в область своего родительского контейнера (например, <div> на странице), при этом сохраняя исходные пропорции (aspect ratio).

Ключевое отличие от других режимов, например FIT, в том, что ENVELOP гарантирует, что холст *полностью покроет* доступную область. Это может привести к тому, что часть игрового мира окажется за пределами видимой области, если пропорции области и игры не совпадают. Поэтому данный режим часто используют в связке с ограничениями по минимальному и максимальному размеру, чтобы контролировать этот процесс.

Настройка конфигурации Scale

Основная настройка происходит в объекте config при создании игры. Внутри свойства scale мы определяем режим, целевой DOM-элемент и ключевые размеры.

const config = {
    type: Phaser.AUTO,
    backgroundColor: '#2dab2d',
    scale: {
        mode: Phaser.Scale.ENVELOP,
        parent: 'phaser-example',
        width: 800,
        height: 600,
        min: {
            width: 800,
            height: 600
        },
        max: {
            width: 1600,
            height: 1200
        }
    },
    scene: Example
};

* mode: Устанавливает режим масштабирования. В нашем случае — Phaser.Scale.ENVELOP. * parent: ID DOM-элемента, внутрь которого будет помещен игровой холст. * width и height: Это *базовое* или *номинальное* разрешение вашей игры (800x600). На этом разрешении игра отрисовывается «как есть», 1 пиксель игры равен 1 пикселю на холсте. * min и max: Эти объекты задают жесткие границы, за которые не сможет выйти масштабированный холст. Они определены в пикселях.

Как работают min и max?

Свойства min и max устанавливают абсолютные границы для физического размера игрового холста в пикселях.

* **Минимальный размер (min)**: Если расчетный размер холста по логике режима ENVELOP окажется меньше указанных здесь значений (например, на очень маленьком экране), холст будет принудительно увеличен до размеров min.width и min.height. В нашем примере игра никогда не будет отображаться в области меньше 800x600 пикселей. Это защищает игровое пространство от сильного сжатия, при котором контент станет нечитаемым.

* **Максимальный размер (max)**: Если расчетный размер по логике ENVELOP окажется больше указанных здесь значений (например, на огромном 4K-мониторе), холст будет принудительно ограничен размерами max.width и max.height. В примере игра не займет область больше 1600x1200 пикселей. Это предотвращает чрезмерное растягивание пиксель-арта или растровых изображений, сохраняя качество графики.

Таким образом, игра будет масштабироваться в диапазоне от 800x600 до 1600x1200, следуя правилу ENVELOP, но не выходя за эти рамки.

Рекомендации по использованию в сцене

При использовании ENVELOP с min/max важно правильно располагать объекты в сцене, особенно фон. В предоставленном примере фоновая картинка позиционируется в точке (0, 0) с установленным setOrigin(0).

create ()
{
    this.add.image(0, 0, 'pic').setOrigin(0);
}

Метод setOrigin(0) устанавливает точку привязки (origin) изображения в его левый верхний угол. Это гарантирует, что при любом масштабировании и возможной обрезке (так как ENVELOP может скрывать часть контента) изображение будет всегда начинаться от левого верхнего угла игрового мира. Если бы точка привязки была по умолчанию в центре (0.5), при обрезке можно было бы увидеть черные или фоновые края по углам. Для фоновых или заполняющих весь мир изображений такая привязка к углу — стандартная практика.

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

Использование связки Phaser.Scale.ENVELOP с параметрами min и max дает надежный контроль над отображением игры на различных экранах. Вы защищаете минимальную читаемость интерфейса и предотвращаете максимальное ухудшение качества графики. Для экспериментов попробуйте: 1. Изменить значения min и max, чтобы увидеть, как игра ведет себя на экранах разного размера. 2. Заменить режим на Phaser.Scale.FIT и сравнить поведение — FIT гарантирует, что вся игра будет видна, но может появиться пустое пространство (поля) вокруг. 3. Добавить в сцену элементы интерфейса (HUD) и использовать для них отдельную камеру или систему позиционирования относительно краев экрана, чтобы они оставались доступными при обрезке игрового мира.