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

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

Версия 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.WIDTH_CONTROLS_HEIGHT,
        _parent: 'phaser-example',
        width: 800,
        height: 600
    },
    scene: Example
};

const game = new Phaser.Game(config);

Суть режима WIDTH_CONTROLS_HEIGHT

Режим масштабирования Phaser.Scale.WIDTH_CONTROLS_HEIGHT — это один из нескольких режимов, управляющих тем, как игра вписывается в область просмотра (viewport). Его логика проста, но эффективна:

* **Ширина является главной.** Игровое поле (game canvas) всегда будет растягиваться на 100% доступной ширины родительского контейнера (например, div на странице). * **Высота вычисляется автоматически.** Система рассчитывает высоту, строго сохраняя исходное соотношение сторон (aspect ratio), заданное в конфигурации (в нашем случае 800x600, то есть 4:3). * **Итог:** Игра всегда занимает всю доступную ширину, а её высота динамически меняется, чтобы картинка не искажалась. По бокам не будет пустых полей (в отличие от FIT), но сверху и снизу они могут появиться, если пропорции экрана и игры не совпадают.

Этот подход идеален, когда вы хотите, чтобы основная игровая механика или интерфейс, завязанные на ширину экрана, оставались неизменными, а вертикальное пространство адаптировалось.

Разбор конфигурации масштабирования

Вся магия происходит внутри объекта scale конфигурации игры. Давайте посмотрим на ключевые параметры.

scale: {
    mode: Phaser.Scale.WIDTH_CONTROLS_HEIGHT,
    _parent: 'phaser-example',
    width: 800,
    height: 600
}

* mode: Phaser.Scale.WIDTH_CONTROLS_HEIGHT — включает нужный нам режим адаптации. * _parent: 'phaser-example' — указывает ID HTML-элемента (например, <div id="phaser-example">), внутрь которого будет встроен canvas. Если этот параметр не указать, игра будет привязана к body. * width: 800 и height: 600 — это **исходные, внутренние размеры** вашей игровой сцены (game world). Именно это соотношение (4:3) будет сохраняться при масштабировании. Все координаты в игре (как (0, 0) для изображения) отсчитываются от этой виртуальной области.

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

Код сцены в этом примере минималистичен и служит для демонстрации принципа. Он загружает и отображает одно изображение.

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

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

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

В методе create происходит самое важное: 1. this.add.image(0, 0, 'pic') — создает игровой объект Image в точке с координатами (0, 0) **исходного игрового мира** (800x600). 2. .setOrigin(0) — устанавливает точку выравнивания (origin) изображения в его левый верхний угол (0, 0). Без этой настройки изображение центрировалось бы относительно точки (0,0), и мы бы не увидели его верхний левый угол в углу canvas.

**Почему это наглядно?** Когда вы меняете ширину окна браузера, изображение всегда растягивается на 100% по ширине. Его высота при этом меняется пропорционально, а точка (0,0) мира остается жестко привязанной к левому верхнему углу изменяющегося canvas. Вы видите, как работает привязка игрового мира к области отображения.

Практическое применение и нюансы

Используйте WIDTH_CONTROLS_HEIGHT, когда дизайн игры ориентирован на контроль по ширине.

* **Горизонтальные скроллеры или "бесконечные бегуны"**: Вы можете быть уверены, что путь персонажа всегда будет занимать всю ширину экрана, а сложность (расстояние между препятствиями) не будет меняться от устройства к устройству. * **Карточные игры или интерфейсы с колонками**: Расположение элементов в ряд будет стабильным.

**Важный нюанс:** Поскольку высота canvas меняется, вам может потребоваться динамически перераспределять игровые объекты по вертикали или использовать камеру для скроллинга, если контента становится больше, чем видимая область. Все расчеты коллизий и позиционирования внутри сцены продолжают работать в координатах исходного мира (800x600), Phaser автоматически преобразует их в пиксели на экране.

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

Режим Scale.WIDTH_CONTROLS_HEIGHT — это мощный инструмент для создания игр с адаптивным, но предсказуемым поведением по ширине. Он избавляет от необходимости вручную пересчитывать размеры при ресайзе, делегируя эту работу движку. **Идеи для экспериментов:** 1. Замените статическое изображение на тайлсет или несколько спрайтов, расположенных в строку, и убедитесь, что их относительное горизонтальное положение не ломается. 2. Добавьте простой горизонтальный скроллинг камеры и проверьте, как меняется ощущение от игры на очень широком и очень узком экране. 3. Попробуйте комбинировать этот режим с другими настройками Scale Manager, например, autoCenter, чтобы управлять выравниванием игры в появившихся вертикальных полях.