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

При разработке игр часто возникает необходимость адаптировать игровую область под разные размеры экрана или изменять её во время выполнения. Жёстко заданные размеры сцены могут ограничивать геймдизайн. В этой статье мы разберём простой, но мощный класс 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, который вычисляет оптимальный размер для текущего окна браузера с сохранением пропорций игры.