О чем этот пример
Когда вы делаете игру, которая должна работать на разных экранах, важно не только растягивать контент, но и задавать разумные границы. Без ограничений игра может выглядеть растянутой на огромном мониторе или нечитаемой на крошечном окне браузера. В этом примере мы разберем, как использовать параметры `min` и `max` в конфигурации масштабирования Phaser (`Phaser.Scale`). Это позволит вашей игре сохранять удобный интерфейс и производительность, автоматически подстраиваясь под размер окна, но в рамках заданных вами пределов.
Версия 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('rain', 'assets/pics/thalion-rain.png');
this.load.image('logo', 'assets/sprites/phaser3-logo-x2.png');
}
create ()
{
this.bg = this.add.tileSprite(0, 0, this.scale.width, this.scale.height, 'rain').setOrigin(0);
this.logo = this.add.sprite(this.scale.width / 2, this.scale.height / 2, 'logo');
this.scale.on('resize', this.resize, this);
}
resize (gameSize, baseSize, displaySize, resolution)
{
const width = gameSize.width;
const height = gameSize.height;
this.cameras.resize(width, height);
this.bg.setSize(width, height);
this.logo.setPosition(width / 2, height / 2);
}
}
const config = {
type: Phaser.AUTO,
backgroundColor: '#2dab2d',
scale: {
mode: Phaser.Scale.RESIZE,
parent: 'phaser-example',
width: '100%',
height: '100%',
min: {
width: 800,
height: 600
},
max: {
width: 1600,
height: 1200
}
},
scene: Example
};
const game = new Phaser.Game(config);
Настройка Scale Manager: сердце адаптивности
Ключ к управлению размерами игры лежит в конфигурации свойства scale при создании экземпляра Phaser.Game. В данном примере используется режим Phaser.Scale.RESIZE, который динамически меняет размеры рендера игры под размер ее родительского элемента в HTML.
Особое внимание стоит уделить полям min и max. Они определяют абсолютные минимальные и максимальные размеры внутренней области отрисовки (так называемого "game size"), независимо от того, насколько большое или маленькое окно у пользователя.
scale: {
mode: Phaser.Scale.RESIZE,
parent: 'phaser-example',
width: '100%',
height: '100%',
min: {
width: 800,
height: 600
},
max: {
width: 1600,
height: 1200
}
}
Что это значит на практике? Если пользователь растянет окно браузера на весь экран с разрешением 4K, внутренний размер игры не превысит 1600x1200 пикселей. И наоборот, если окно будет очень маленьким, игра гарантированно не сожмется меньше 800x600, предотвращая "склеивание" интерфейса.
Обработка события 'resize': динамическое обновление сцены
Когда размер окна меняется, Scale Manager генерирует событие 'resize'. Чтобы игра корректно отреагировала на это изменение (например, пересчитала позиции элементов), мы должны подписаться на это событие.
В методе create() сцены мы добавляем слушатель. Важно передать контекст (this) третьим аргументом, чтобы внутри функции-обработчика this ссылался на текущую сцену.
create ()
{
this.bg = this.add.tileSprite(0, 0, this.scale.width, this.scale.height, 'rain').setOrigin(0);
this.logo = this.add.sprite(this.scale.width / 2, this.scale.height / 2, 'logo');
this.scale.on('resize', this.resize, this);
}
Изначально мы создаем фон как TileSprite, который будет растягиваться на всю доступную область, и спрайт логотипа в центре экрана, используя актуальные размеры из this.scale.width и this.scale.height.
Функция resize: перестраиваем мир под новые размеры
Функция resize вызывается каждый раз при изменении размера. Она получает несколько параметров, но в данном примере используется только первый — gameSize. Этот объект содержит новые ширину и высоту внутренней области отрисовки, уже учтя ограничения min и max.
Логика обработки состоит из трех ключевых шагов:
1. **Обновление камер:** Все камеры в сцене должны быть перенастроены под новый размер. Для этого используется метод this.cameras.resize(width, height).
2. **Обновление фона:** Размер TileSprite с фоном меняется, чтобы он заполнил новую область.
3. **Перемещение элементов:** Ключевые игровые объекты (как логотип) перепозиционируются, чтобы остаться в центре.
resize (gameSize, baseSize, displaySize, resolution)
{
const width = gameSize.width;
const height = gameSize.height;
this.cameras.resize(width, height);
this.bg.setSize(width, height);
this.logo.setPosition(width / 2, height / 2);
}
Без вызова this.cameras.resize() область видимости камеры останется прежней, что может привести к отображению только части контента или черных полей.
Что попробовать дальше
Использование min и max в настройках Scale Manager — это простой и эффективный способ обеспечить базовую адаптивность игры, защитив ее интерфейс от экстремальных размеров окна. Механизм работает автоматически: вам нужно лишь правильно обработать событие resize.
**Идеи для экспериментов:**
1. Попробуйте изменить значения min и max в конфиге и понаблюдайте, как игра ведет себя при растягивании окна.
2. Добавьте в сцену больше UI-элементов (кнопки, панели здоровья) и реализуйте их перепозиционирование в функции resize, используя не только центр, но и углы экрана.
3. Исследуйте другие режимы масштабирования, например Phaser.Scale.FIT или Phaser.Scale.ENVELOP, и посмотрите, как они сочетаются с ограничениями по размеру.
