Адаптация UI под размер экрана

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


Настройка масштабирования игры

Phaser использует объект конфигурации config, где можно задать параметры масштабирования через свойство scale. Основные режимы масштабирования:

const config = {
    type: Phaser.AUTO,
    width: 800,
    height: 600,
    scale: {
        mode: Phaser.Scale.FIT,
        autoCenter: Phaser.Scale.CENTER_BOTH
    },
    scene: [MainScene]
};
  • Phaser.Scale.FIT – масштабирует игру, сохраняя пропорции, чтобы весь контент помещался на экране.
  • Phaser.Scale.ENVELOP – масштабирует игру так, чтобы экран был полностью заполнен, даже если часть контента выходит за пределы.
  • Phaser.Scale.RESIZE – динамически подстраивает размеры канваса под размер контейнера.

autoCenter позволяет автоматически выравнивать игру по центру контейнера:

  • CENTER_BOTH – центрирует по горизонтали и вертикали.
  • CENTER_HORIZONTALLY или CENTER_VERTICALLY – по одной оси.

Динамическое позиционирование UI

Для элементов интерфейса (кнопок, панелей, текста) важно использовать относительные координаты вместо фиксированных пикселей. В Phaser это достигается с помощью размеров сцены:

const centerX = this.cameras.main.width / 2;
const centerY = this.cameras.main.height / 2;

const button = this.add.image(centerX, centerY, 'buttonTexture');

this.cameras.main.width и height всегда соответствуют текущему размеру канваса, что позволяет корректно позиционировать элементы при изменении размера окна.


Масштабирование спрайтов и текстов

Чтобы элементы интерфейса сохраняли читаемость и соотношение сторон на разных экранах, применяют:

  • Пропорциональное масштабирование спрайтов:
button.setScale(this.cameras.main.width / 800);

Здесь 800 — базовая ширина, под которую разрабатывался интерфейс.

  • Масштабирование текста через стиль:
const fontSize = Math.round(this.cameras.main.width / 25);
this.add.text(centerX, centerY - 100, 'Score: 0', {
    fontSize: `${fontSize}px`,
    color: '#ffffff'
}).setOrigin(0.5);

Использование setOrigin(0.5) позволяет центрировать текст относительно координат.


Использование контейнеров для UI

Phaser поддерживает контейнеры (Phaser.GameObjects.Container), позволяющие сгруппировать несколько объектов и управлять их позиционированием как единым блоком. Это удобно для сложных панелей и меню.

const uiContainer = this.add.container(centerX, centerY);

const panel = this.add.image(0, 0, 'panel');
const playButton = this.add.image(0, 50, 'playButton');

uiContainer.add([panel, playButton]);

uiContainer.setScale(this.cameras.main.width / 800);

При изменении размера сцены можно просто пересчитать масштаб и позицию контейнера, а все дочерние элементы адаптируются автоматически.


Обработка изменения размера окна

Phaser поддерживает событие resize для камеры, что позволяет динамически адаптировать UI:

this.scale.on('resize', (gameSize, baseSize, displaySize, resolution) => {
    const width = gameSize.width;
    const height = gameSize.height;

    centerX = width / 2;
    centerY = height / 2;

    uiContainer.setPosition(centerX, centerY);
});

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


Использование относительных единиц для отступов и размеров

При разработке интерфейса стоит избегать абсолютных пикселей и использовать процентные единицы относительно ширины и высоты сцены:

const margin = this.cameras.main.width * 0.05;

const scoreText = this.add.text(margin, margin, 'Score: 0', {
    fontSize: `${this.cameras.main.width / 30}px`,
    color: '#ffffff'
});

Такой подход обеспечивает стабильное расстояние между элементами и их читаемость на всех устройствах.


Практические рекомендации

  • Задавать базовые размеры игры под оптимальное разрешение (например, 800x600 или 1280x720) и масштабировать относительно них.
  • Для кнопок и панелей использовать контейнеры с пропорциональным масштабированием.
  • Тексты масштабировать динамически, исходя из ширины канваса.
  • Для мобильных устройств проверять ориентацию и адаптировать UI под ландшафтный и портретный режим.
  • Использовать Phaser.Scale.FIT или Phaser.Scale.RESIZE для корректного отображения игры на разных экранах.

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