О чем этот пример
При разработке игр часто возникает необходимость адаптировать игровую область под разные размеры экрана или изменять её во время выполнения. Жёстко заданные размеры сцены могут ограничивать геймдизайн. В этой статье мы разберём простой, но мощный класс Controller, который позволяет динамически управлять размером камеры сцены, делая вашу игру более гибкой и отзывчивой. Этот подход особенно полезен для игр с изменяемым уровнем сложности, процедурно генерируемыми локациями или для реализации паузы и меню, которые требуют изменения области отрисовки без перезагрузки всей сцены.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Controller extends Phaser.Scene {
constructor ()
{
super();
}
resize (width, height)
{
if (width === undefined) { width = this.game.config.width; }
if (height === undefined) { height = this.game.config.height; }
this.cameras.resize(width, height);
}
}
Анатомия класса Controller
Класс Controller наследуется от Phaser.Scene. Это означает, что он представляет собой полноценную сцену в Phaser, но с добавленной специальной логикой для управления её размерами.
class Controller extends Phaser.Scene {
constructor ()
{
super();
}
}
Конструктор вызывает super(), инициализируя стандартную функциональность сцены. Вся магия содержится в единственном методе resize.
Метод resize: сердце контроллера
Метод resize принимает два аргумента: ширину (width) и высоту (height). Его задача — изменить размер основной камеры сцены (this.cameras.main) на указанные значения.
resize (width, height)
{
if (width === undefined) { width = this.game.config.width; }
if (height === undefined) { height = this.game.config.height; }
this.cameras.resize(width, height);
}
Первые две строки — это защита от undefined. Если метод вызван без аргументов или с пропущенным одним из них, в качестве значения по умолчанию берутся базовые размеры игры из конфигурации (this.game.config). Это обеспечивает безопасность вызова и возврат к исходному состоянию.
Ключевая строка — this.cameras.resize(width, height). Здесь this.cameras — это менеджер камер сцены, а метод resize изменяет размер её *основной* камеры. Это влияет на область игрового мира, которая видна игроку.
Практическое применение: когда это нужно?
Динамическое изменение размера камеры открывает несколько сценариев использования.
1. **Адаптация под область просмотра:** Вы можете привязать вызов this.scene.get('Controller').resize(newWidth, newHeight) к событию 'resize' браузера, чтобы игровая область всегда занимала доступное пространство.
2. **Режимы игры:** Например, при переходе в меню паузы можно уменьшить игровую область, освободив место для интерфейса.
3. **Масштабирование уровня:** Для игр с зумом или изменяемыми границами мира.
Пример вызова из другой сцены:
// Предположим, наша сцена Controller имеет ключ 'Controller'
this.scene.get('Controller').resize(800, 600);
Важные нюансы и ограничения
1. **Изменяется камера, а не мир.** Метод resize меняет размер *видимой области* (камеры), а не физические размеры игрового мира или положения объектов в нём. Объекты за новыми границами просто перестанут быть видны.
2. **Одна камера.** В примере используется this.cameras.resize(), что применяется к основной камере. Если в вашей сцене несколько камер, потребуется управлять ими отдельно.
3. **Координаты.** Изменение размера камеры не меняет её точку привязки (anchor) или положение. Центр камеры останется прежним, из-за чего видимая область может сместиться относительно игрового мира.
Для управления положением камеры после ресайза вам, вероятно, понадобится дополнительная логика, например, центрирование её на определённом объекте.
Что попробовать дальше
Класс Controller — это элегантное решение для динамического управления областью отрисовки в Phaser. Он отделяет логику изменения размера от основного игрового процесса, соблюдая принцип единственной ответственности.
**Идеи для экспериментов:**
1. Расширьте метод resize, чтобы он автоматически центрировал камеру на главном герое после изменения размера.
2. Добавьте плавную анимацию изменения размера с помощью твинов Phaser вместо мгновенного применения.
3. Создайте метод setFullscreen, который вычисляет оптимальный размер для текущего окна браузера с сохранением пропорций игры.
