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

Создание игр, которые одинаково хорошо выглядят на экранах разных размеров — частая задача для разработчиков. Особенно критично это для пиксель-арта, где неаккуратное масштабирование может "смазать" чёткие пиксельные границы и испортить визуальный стиль. Пример 'fit and snap' демонстрирует, как использовать менеджер масштабирования Phaser, чтобы игра автоматически подстраивалась под размер окна браузера, сохраняя целостность ваших пиксельных ассетов.

Версия 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/dr-ick.png');
    }

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

const config = {
    type: Phaser.AUTO,
    backgroundColor: '#2dab2d',
    pixelArt: true,
    scale: {
        mode: Phaser.Scale.FIT,
        parent: 'phaser-example',
        autoCenter: Phaser.Scale.CENTER_BOTH,
        width: 240,
        height: 160,
        min: {
            width: 240,
            height: 160
        },
        snap: {
            width: 240,
            height: 160
        }
    },
    scene: Example
};

const game = new Phaser.Game(config);

Зачем нужен Scale Manager?

Раньше разработчикам приходилось вручную рассчитывать масштаб холста и позиционирование элементов при изменении размеров окна. Phaser Scale Manager берёт эту рутину на себя. Он автоматически управляет элементом <canvas>, его CSS-свойствами и внутренней системой координат игры. Это позволяет вам, как разработчику, работать в фиксированной системе координат (например, 240x160), не беспокоясь о реальном разрешении экрана пользователя.

В примере ключевая цель — отобразить изображение, загруженное как 'pic', так, чтобы оно всегда было видно целиком, сохраняло свои пропорции и чёткость пикселей.

Конфигурация scale: FIT, CENTER_BOTH и min

Сердце примера — объект конфигурации scale в основном конфиге игры. Разберём его ключевые свойства.

scale: {
    mode: Phaser.Scale.FIT,
    parent: 'phaser-example',
    autoCenter: Phaser.Scale.CENTER_BOTH,
    width: 240,
    height: 160,
    min: {
        width: 240,
        height: 160
    }
}

* mode: Phaser.Scale.FIT — это основной режим масштабирования. Он гарантирует, что игровая область (240x160) будет пропорционально увеличена или уменьшена, чтобы целиком поместиться в отведённый ей родительский контейнер, без обрезки. По бокам или сверху/снизу могут появиться чёрные полосы (или полосы фона игры). * autoCenter: Phaser.Scale.CENTER_BOTH — автоматически выравнивает отмасштабированную игровую область по центру родительского контейнера и по горизонтали, и по вертикали. * width и height (240, 160) — это внутреннее, «игровое» разрешение. В этой системе координат размещаются все ваши игровые объекты. * Объект min устанавливает минимальный размер, до которого может быть уменьшена игровая область. Это страховка от того, что игра станет слишком маленькой.

Магия свойства snap для пиксель-арта

Свойство snap — это секретный ингредиент для сохранения чёткости пиксель-арта. Оно работает в паре с mode: Phaser.Scale.FIT.

snap: {
    width: 240,
    height: 160
}

Без snap Phaser.FIT может масштабировать холст до нецелых значений (например, в 1.78 раза). При отрисовке пиксельной графики на таком холсте браузер будет применять сглаживание (anti-aliasing), что сделает края размытыми.

Свойство snap заставляет менеджер масштабирования подбирать такой коэффициент увеличения, чтобы итоговый размер холста в пикселях был кратен базовому разрешению (240x160). Например, вместо множителя 1.78 будет выбран 2. Это гарантирует, что каждый виртуальный пиксель игры будет отрисован ровно 2x2, 3x3 и т.д. реальными пикселями экрана, сохраняя идеальную чёткость.

Важно: для работы snap также необходимо установить pixelArt: true в основном конфиге игры. Этот флаг отключает встроенное в браузер сглаживание изображений (imageSmoothing).

Размещение объектов в фиксированной системе координат

Благодаря настройкам scale, вся логика позиционирования в коде сцены работает в простой, предсказуемой системе координат 240x160. В методе create мы размещаем изображение в точке (0, 0).

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

* this.add.image(0, 0, 'pic') — создаёт объект изображения в левом верхнем углу игрового мира. * .setOrigin(0) — устанавливает точку привязки (origin) изображения в его левый верхний угол (0,0). Это значит, что координаты (0,0) объекта совпадут с левым верхним углом его текстуры. В сочетании с координатами (0,0) сцены это гарантирует, что изображение будет плотно прижато к краю игровой области.

Вы можете размещать другие объекты, используя эти же координаты (от 0 до 240 по X и от 0 до 160 по Y), и Scale Manager позаботится об их правильном отображении на любом экране.

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

Настройка scale с режимом FIT, центрированием CENTER_BOTH и свойством snap — это мощный и элегантный способ создать адаптивный интерфейс для пиксель-арт игры, который сохраняет чёткость графики. Для экспериментов попробуйте: 1. Изменить базовые width и height на другие значения и посмотреть, как меняется масштабирование. 2. Убрать свойство snap и сравнить чёткость изображения при изменении размера окна. 3. Заменить Phaser.Scale.FIT на Phaser.Scale.ENVELOP (изображение заполнит весь контейнер, возможна обрезка) и оценить разницу в поведении.