О чем этот пример
Тайловые карты — основа для создания уровней в 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-игр. Для экспериментов попробуйте: загрузить карту с несколькими слоями (например, для фона и объектов), добавить на карту спрайты с коллизиями или реализовать плавное слежение камеры за игровым персонажем вместо ручного управления.
