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

При разработке игр на Phaser часто возникает необходимость загрузить ресурсы (например, тайловые карты) до создания сцены. Это позволяет избежать мерцания и показа индикатора загрузки, обеспечивая плавный старт уровня. В этой статье мы рассмотрим, как объявить ресурсы для предзагрузки прямо в конструкторе сцены, используя `pack`, и затем создать тайловую карту с камерой, управляемой с клавиатуры. Этот подход полезен для создания изолированных уровней или мини-игр, где все ресурсы известны заранее.

Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.

Живой запуск

Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.

Исходный код


class Example extends Phaser.Scene
{
    constructor ()
    {
        super({
            pack: {
                files: [
                    {
                        type: 'tilemapTiledJSON',
                        key: 'map',
                        url: 'assets/tilemaps/maps/cybernoid.json'
                    },
                    {
                        type: 'image',
                        key: 'tiles',
                        url: 'assets/tilemaps/tiles/cybernoid.png'
                    }
                ]
            }
        });
    }

    create ()
    {
        const map = this.make.tilemap({ key: 'map' });

        const tiles = map.addTilesetImage('cybernoid', 'tiles');

        const layer = map.createLayer(0, tiles, 0, 0);

        this.cameras.main.setBounds(0, 0, map.widthInPixels, map.heightInPixels);

        const cursors = this.input.keyboard.createCursorKeys();

        const controlConfig = {
            camera: this.cameras.main,
            left: cursors.left,
            right: cursors.right,
            up: cursors.up,
            down: cursors.down,
            speed: 0.5
        };

        this.controls = new Phaser.Cameras.Controls.FixedKeyControl(controlConfig);
    }

    update (time, delta)
    {
        this.controls.update(delta);
    }
}

const config = {
    type: Phaser.AUTO,
    width: 800,
    height: 600,
    backgroundColor: '#2d2d2d',
    parent: 'phaser-example',
    pixelArt: true,
    scene: Example
};

const game = new Phaser.Game(config);

Объявление ресурсов в конструкторе сцены

Вместо использования стандартного метода предзагрузки (preload) мы можем указать файлы для загрузки непосредственно в конструкторе сцены через параметр pack. Это мощная альтернатива, особенно когда сцена самодостаточна.

Конфигурация pack принимает массив files, где каждый объект описывает один ресурс. Ключевые поля: - type: Тип загружаемого ресурса, например 'tilemapTiledJSON' для карт из Tiled. - key: Уникальный строковый ключ, по которому ресурс будет доступен в коде. - url: Путь к файлу.

constructor ()
{
    super({
        pack: {
            files: [
                {
                    type: 'tilemapTiledJSON',
                    key: 'map',
                    url: 'assets/tilemaps/maps/cybernoid.json'
                },
                {
                    type: 'image',
                    key: 'tiles',
                    url: 'assets/tilemaps/tiles/cybernoid.png'
                }
            ]
        }
    });
}

Phaser загрузит эти файлы до вызова метода create() сцены. Обратите внимание, что key для тайлсета ('tiles') не обязательно должен совпадать с именем набора тайлов внутри JSON-файла карты.

Создание тайловой карты и слоя

В методе create() мы получаем доступ к загруженным ресурсам и строим карту.

Сначала создаем объект тайловой карты, используя ключ 'map', который указали в pack.

const map = this.make.tilemap({ key: 'map' });

Затем добавляем тайлсет. Первый аргумент 'cybernoid' — это имя набора тайлов (tileset name), которое прописано внутри JSON-файла карты (cybernoid.json). Второй аргумент 'tiles' — это ключ загруженного изображения.

const tiles = map.addTilesetImage('cybernoid', 'tiles');

После этого создаем слой. Аргументы метода createLayer: индекс слоя в данных карты (0 — первый слой), тайлсет, и координаты X, Y для отрисовки.

const layer = map.createLayer(0, tiles, 0, 0);

Теперь карта отображена на сцене.

Настройка камеры и элементов управления

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

Устанавливаем границы камеры равными размерам карты в пикселях. Это предотвратит скроллинг за пределы уровня.

this.cameras.main.setBounds(0, 0, map.widthInPixels, map.heightInPixels);

Создаем объект для отслеживания нажатий клавиш-стрелок.

const cursors = this.input.keyboard.createCursorKeys();

Настраиваем конфигурацию для контроллера камеры FixedKeyControl. В ней указываем, какую камеру двигать (this.cameras.main), какие клавиши отвечают за направления, и скорость перемещения.

const controlConfig = {
    camera: this.cameras.main,
    left: cursors.left,
    right: cursors.right,
    up: cursors.up,
    down: cursors.down,
    speed: 0.5
};

this.controls = new Phaser.Cameras.Controls.FixedKeyControl(controlConfig);

Контроллер необходимо обновлять каждый кадр, что делается в методе update().

update (time, delta)
{
    this.controls.update(delta);
}

Параметр delta (время, прошедшее с прошлого кадра) обеспечивает плавное движение камеры независимо от частоты кадров.

Что попробовать дальше

Использование pack в конструкторе сцены — это удобный способ предзагрузить специфичные для уровня ресурсы, делая код сцены более модульным. Вы научились создавать тайловую карту и настраивать камеру с клавиатурным управлением для её осмотра. Для экспериментов попробуйте: 1. Добавить в pack загрузку спрайта игрока и разместить его на карте. 2. Изменить скорость камеры (speed) или привязать управление к другим клавишам. 3. Использовать this.cameras.main.zoom для реализации приближения и отдаления. 4. Загрузить несколько карт и переключаться между ними, изменяя ключ key в this.make.tilemap.