О чем этот пример
Современные мобильные игры должны корректно работать как в портретной, так и в альбомной ориентации. Phaser предоставляет удобный инструмент `Scale Manager` для отслеживания изменений ориентации устройства и адаптации контента в реальном времени. Эта статья покажет, как слушать события поворота экрана и динамически менять видимость и состояние игровых объектов, что критически важно для создания удобного мобильного интерфейса.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
text;
ship;
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('pic', 'assets/pics/spaceship.png');
}
create ()
{
this.ship = this.add.image(0, 0, 'pic').setOrigin(0);
this.text = this.add.text(320, 128, 'Please set your\nphone to landscape', { font: '48px Courier', fill: '#00ff00', align: 'center' }).setOrigin(0.5);
this.checkOriention(this.scale.orientation);
this.scale.on('orientationchange', this.checkOriention, this);
}
checkOriention (orientation)
{
if (orientation === Phaser.Scale.PORTRAIT)
{
this.ship.alpha = 0.2;
this.text.setVisible(true);
}
else if (orientation === Phaser.Scale.LANDSCAPE)
{
this.ship.alpha = 1;
this.text.setVisible(false);
}
}
}
const config = {
type: Phaser.AUTO,
backgroundColor: '#000000',
scale: {
mode: Phaser.Scale.FIT,
parent: 'phaser-example',
autoCenter: 1,
width: 640,
height: 256
},
scene: Example
};
const game = new Phaser.Game(config);
Настройка Scale Manager в конфигурации
Вся работа с ориентацией начинается с правильной конфигурации scale в объекте конфигурации игры. Именно здесь мы задаём базовые правила масштабирования.
const config = {
scale: {
mode: Phaser.Scale.FIT,
parent: 'phaser-example',
autoCenter: 1,
width: 640,
height: 256
},
scene: Example
};
Ключевые параметры:
- mode: Phaser.Scale.FIT гарантирует, что игра будет пропорционально вписана в родительский контейнер без обрезки.
- autoCenter: 1 центрирует игровое поле по горизонтали и вертикали.
- width и height задают внутреннее разрешение игры (размер игрового мира), под которое создаются ваши ассеты.
Получение текущей ориентации и подписка на события
В методе create() сцены мы можем сразу получить текущую ориентацию и подписаться на её изменения. Это делается с помощью свойства this.scale.orientation и события orientationchange.
create ()
{
// Создаём игровые объекты
this.ship = this.add.image(0, 0, 'pic').setOrigin(0);
this.text = this.add.text(320, 128, 'Please set your\nphone to landscape', { font: '48px Courier', fill: '#00ff00', align: 'center' }).setOrigin(0.5);
// Проверяем ориентацию при старте
this.checkOriention(this.scale.orientation);
// Подписываемся на событие изменения ориентации
this.scale.on('orientationchange', this.checkOriention, this);
}
Метод this.scale.on принимает три аргумента: имя события, функцию-обработчик и контекст (this), который будет передан в эту функцию. Без указания контекста this внутри checkOriention будет неопределён.
Обработчик изменений: метод checkOriention
Ядро логики находится в методе checkOriention. Он получает текущую ориентацию в качестве аргумента и сравнивает её с константами Phaser.Scale.PORTRAIT и Phaser.Scale.LANDSCAPE.
checkOriention (orientation)
{
if (orientation === Phaser.Scale.PORTRAIT)
{
this.ship.alpha = 0.2;
this.text.setVisible(true);
}
else if (orientation === Phaser.Scale.LANDSCAPE)
{
this.ship.alpha = 1;
this.text.setVisible(false);
}
}
В портретном режиме корабль становится полупрозрачным (альфа-канал 0.2), а текстовое предупреждение отображается. В альбомном режиме корабль полностью видим, а текст скрывается. Это наглядный способ дать пользователю понять, как правильно держать устройство.
Практические советы и распространённые сценарии
Простого переключения видимости часто недостаточно. Вот что ещё можно делать в обработчике orientationchange:
// Пример: изменение положения UI-элементов
if (orientation === Phaser.Scale.LANDSCAPE) {
uiPanel.setPosition(600, 50); // Панель справа
} else {
uiPanel.setPosition(50, 300); // Панель снизу
}
// Пример: перезапуск физического мира
if (orientation === Phaser.Scale.LANDSCAPE) {
this.physics.world.setBounds(0, 0, 800, 400);
} else {
this.physics.world.setBounds(0, 0, 400, 800);
}
Важно помнить, что при смене ориентации физические границы мира (world bounds) не меняются автоматически. Их нужно обновлять вручную, чтобы объекты не "улетали" за экран.
Что попробовать дальше
Scale Manager в Phaser — это мощный и простой инструмент для создания отзывчивых мобильных игр. Для экспериментов попробуйте не скрывать, а перераспределять UI-элементы, менять активность игровых механик (например, в портрете управление тапом, в альбоме — виртуальный джойстик) или динамически подгружать ассеты разного размера в зависимости от ориентации.
