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

Тайловые карты — основа для создания уровней в 2D-играх. Phaser позволяет загружать карты, созданные в редакторах вроде Tiled, используя формат JSON. Это даёт мощный инструмент для быстрого прототипирования и построения сложных игровых миров, отделяя данные уровня от логики игры. В этой статье мы разберём пример загрузки тайловой карты из JSON-файла, её отображения и добавления простого управления камерой. Вы поймёте базовый пайплайн работы с тайлами в Phaser, который можно масштабировать для своих проектов.

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

Живой запуск

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

Исходный код


class Example extends Phaser.Scene
{
    controls;

    preload ()
    {
        this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
        this.load.image('tiles', 'assets/tilemaps/tiles/cybernoid.png');

        this.load.tilemapTiledJSON({
            key: 'map',
            url: 'assets/tilemaps/maps/cybernoid.json'
        });
    }

    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.WEBGL,
    width: 800,
    height: 600,
    backgroundColor: '#2d2d2d',
    parent: 'phaser-example',
    pixelArt: true,
    scene: Example
};

const game = new Phaser.Game(config);

Настройка загрузки ресурсов (preload)

Всё начинается с метода preload. Здесь мы указываем Phaser, какие файлы нужны для сцены. Ключевой момент — использование this.load.tilemapTiledJSON для загрузки карты.

this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('tiles', 'assets/tilemaps/tiles/cybernoid.png');

this.load.tilemapTiledJSON({
    key: 'map',
    url: 'assets/tilemaps/maps/cybernoid.json'
});

Сначала метод setBaseURL задаёт базовый URL для всех последующих загрузок, что удобно, если ресурсы лежат в одной папке. Далее загружается изображение с тайлами ('tiles') — это спрайтшит, из которого будут браться изображения для карты. Затем с помощью this.load.tilemapTiledJSON загружается JSON-файл карты, созданный в Tiled. Обратите внимание, что метод принимает объект с параметрами key (уникальный ключ для обращения к карте) и url (путь к файлу).

Создание и отображение карты (create)

После загрузки ресурсов в методе create мы создаём игровой мир. Основные шаги: создать объект тайловой карты, связать его с изображением тайлов и создать слой для отрисовки.

const map = this.make.tilemap({ key: 'map' });
const tiles = map.addTilesetImage('cybernoid', 'tiles');
const layer = map.createLayer(0, tiles, 0, 0);

Сначала this.make.tilemap создаёт объект карты, используя ключ 'map', который мы задали при загрузке. Затем map.addTilesetImage связывает набор тайлов (tileset) из JSON-файла (в данном случае он называется 'cybernoid') с загруженным изображением 'tiles'. Это критически важный шаг — без него карта не будет знать, какие изображения использовать. Наконец, map.createLayer создаёт визуальный слой. Первый аргумент `0— индекс слоя в карте (в данном случае это основной слой), затем идёт связанный набор тайлов, а последние два аргумента0, 0` — координаты X и Y для отрисовки слоя на сцене.

Управление камерой и игроком

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

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);

Сначала this.cameras.main.setBounds устанавливает границы для основной камеры, равные размерам карты в пикселях (map.widthInPixels, map.heightInPixels). Это предотвращает выход камеры за пределы мира. Далее создаётся объект cursors для отслеживания нажатий стрелок клавиатуры. Затем настраивается конфигурация управления controlConfig, где указывается камера, привязка клавиш и скорость перемещения. Объект Phaser.Cameras.Controls.FixedKeyControl на основе этой конфигурации создаёт готовый контроллер для перемещения камеры. Его нужно обновлять каждый кадр, что происходит в методе update.

Обновление состояния (update)

Для работы динамических элементов, таких как управление камерой, необходим метод update. Он вызывается на каждом кадре игры.

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

Здесь вызывается метод update у контроллера камеры (this.controls). Параметр delta представляет время, прошедшее с предыдущего кадра, в миллисекундах. Его передача контроллеру обеспечивает плавное движение камеры, независящее от частоты кадров.

Конфигурация игры и запуск

Весь пример завершается созданием и запуском экземпляра игры Phaser.Game с необходимой конфигурацией.

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

const game = new Phaser.Game(config);

В объекте config задаются основные параметры: type (рендерер), width и height (размеры canvas), backgroundColor. Ключевой для пиксель-арт игр параметр pixelArt: true включает сглаживание текстур, чтобы они оставались чёткими при масштабировании. scene указывает на класс нашей сцены. Создание new Phaser.Game(config) инициализирует и запускает игру с этой конфигурацией.

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

Вы освоили базовый цикл загрузки и отображения тайловой карты в Phaser. Этот паттерн — основа для создания уровней в огромном количестве 2D-игр. Для экспериментов попробуйте: загрузить карту с несколькими слоями (например, для фона и объектов), добавить на карту спрайты с коллизиями или реализовать плавное слежение камеры за игровым персонажем вместо ручного управления.