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

При разработке игр с пиксельной графикой важно сохранить чёткость и стиль, но при этом адаптировать изображение под разные экраны. Пример использования `Phaser.Scale.FIT` вместе с параметром `zoom` в Scale Manager показывает, как легко решить эту задачу. Вы узнаете, как настроить отображение небольшого игрового холста на любом устройстве без размытия и искажений, что особенно полезно для ретро-игр или проектов с фиксированным разрешением.

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

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

const config = {
    type: Phaser.AUTO,
    backgroundColor: '#2dab2d',
    scale: {
        mode: Phaser.Scale.FIT,
        parent: 'phaser-example',
        width: 160,
        height: 144,
        zoom: 4
    },
    scene: Example
};

const game = new Phaser.Game(config);

Задача: отобразить маленький холст на больших экранах

Исходный размер холста в этом примере — всего 160x144 пикселей. Если растянуть такое изображение на весь экран современного монитора, пиксели превратятся в размытые пятна. Нам нужно увеличить картинку, сохранив чёткие границы каждого пикселя, и при этом вписать её в окно браузера.

Для этого в конфигурации игры используется менеджер масштабирования Phaser Scale Manager с двумя ключевыми параметрами: mode и zoom.

Конфигурация Scale Manager: FIT и ZOOM

Основная магия происходит в объекте scale конфигурации игры. Давайте разберём его параметры.

scale: {
    mode: Phaser.Scale.FIT,
    parent: 'phaser-example',
    width: 160,
    height: 144,
    zoom: 4
}

* mode: Phaser.Scale.FIT — директива для менеджера масштабирования. Режим FIT гарантирует, что игровое поле (с учётом zoom) будет пропорционально вписано в родительский контейнер (parent). По бокам или сверху/снизу могут появиться чёрные полосы (letterboxing), но исходные пропорции игры не исказятся. * width и height — внутреннее логическое разрешение вашей игры. Все координаты и расчёты будут вестись в этих единицах. * zoom: 4 — самый важный параметр для нашей задачи. Он говорит Phaser: "отрисуй каждый логический пиксель игры как блок 4x4 физических пикселя на экране". Таким образом, логический холст 160x144 превратится в холст для отрисовки размером 640x576 пикселей. Именно этот увеличенный холст будет затем масштабирован режимом FIT под размер контейнера.

Как работает сцена

Сцена в этом примере предельно проста. Она загружает одно изображение и отображает его в левом верхнем углу.

preload ()
{
    this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
    this.load.image('pic', 'assets/tests/zoom/title.png');
}

Метод preload задаёт базовый URL для загрузки и загружает картинку title.png под ключом 'pic'.

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

В методе create мы добавляем изображение в точку с координатами (0, 0) — левый верхний угол игрового мира. Вызов .setOrigin(0) устанавливает точку привязки (origin) изображения также в его левый верхний угол, поэтому картинка идеально совпадает с углом холста. Важно понимать, что координаты (0,0) здесь — это координаты внутри логического мира размером 160x144, а не итогового увеличенного холста.

Итоговый результат и визуализация

Вот что происходит при запуске игры: 1. Phaser создаёт внутренний (логический) холст размером 160x144. 2. Из-за параметра zoom: 4 каждый логический пиксель отрисовывается как квадрат 4x4. Фактический размер холста для отрисовки становится 640x576. 3. Менеджер масштабирования (FIT) берёт этот холст 640x576 и подгоняет его под размер HTML-элемента с id 'phaser-example'. Если контейнер шире или уже, Phaser пропорционально увеличит или уменьшит весь холст 640x576, добавляя чёрные поля при необходимости.

Ключевой вывод: ваша игра "думает", что работает в маленьком разрешении (160x144), что упрощает расчёты и позиционирование. Игрок же видит крупную, чёткую пиксельную картинку, которая аккуратно вписана в его окно браузера. Само изображение не растягивается и не интерполируется — оно остаётся острым.

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

Сочетание Phaser.Scale.FIT и zoom — мощный инструмент для разработки игр с фиксированным разрешением. Оно отделяет логический размер игры от физического отображения, сохраняя контроль над пиксельной эстетикой. Попробуйте поэкспериментировать: измените значение zoom на 2 или 8, чтобы увидеть разницу в размере и чёткости. Замените режим FIT на Phaser.Scale.ENVELOP — он также сохранит пропорции, но будет масштабировать изображение, чтобы заполнить весь контейнер, возможно, обрезая края. Это полезно для фонов, которые не боятся кадрирования.