О чем этот пример
При разработке игр с тайловыми картами часто возникает необходимость комбинировать различные наборы спрайтов для создания детализированных и разнообразных уровней. В этой статье мы разберем, как загружать и использовать несколько тайлсетов в одном слое карты в Phaser, что является ключевым навыком для создания визуально насыщенных игровых миров. Вы научитесь подключать несколько графических наборов, загруженных из редактора Tiled, и управлять камерой для навигации по большой карте.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
constructor()
{
super();
}
preload()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('ground', 'assets/tilemaps/tiles/kenny_ground_64x64.png');
this.load.image('items', 'assets/tilemaps/tiles/kenny_items_64x64.png');
this.load.image('platformer', 'assets/tilemaps/tiles/kenny_platformer_64x64.png');
this.load.tilemapTiledJSON('map', 'assets/tilemaps/maps/multi-tileset.json');
}
create()
{
var map = this.make.tilemap({ key: 'map' });
var groundTiles = map.addTilesetImage('kenny_ground_64x64', 'ground');
var itemTiles = map.addTilesetImage('kenny_items_64x64', 'items');
var platformTiles = map.addTilesetImage('kenny_platformer_64x64', 'platformer');
// To use multiple tilesets in a single layer, pass them in an array like this:
map.createLayer('Tile Layer 1', [ groundTiles, itemTiles, platformTiles ]);
// Or you can pass an array of strings, where they = the Tileset name
// map.createLayer('Tile Layer 1', [ 'kenny_ground_64x64', 'kenny_items_64x64', 'kenny_platformer_64x64' ]);
this.cameras.main.setBounds(0, 0, map.widthInPixels, map.heightInPixels);
var cursors = this.input.keyboard.createCursorKeys();
var 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);
var help = this.add.text(16, 16, 'Arrow keys to scroll', {
fontSize: '18px',
padding: { x: 10, y: 5 },
backgroundColor: '#000000',
fill: '#ffffff'
});
help.setScrollFactor(0);
}
update(time, delta)
{
this.controls.update(delta);
}
}
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
backgroundColor: '#2d2d2d',
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Загрузка ресурсов: карта и тайлсеты
В методе preload() происходит загрузка всех необходимых ресурсов. Важно загрузить как саму карту в формате JSON, экспортированную из Tiled, так и все изображения тайлсетов, которые на ней используются. Обратите внимание, что метод load.setBaseURL() устанавливает базовый URL для всех последующих загрузок, что позволяет указывать только относительные пути.
preload()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('ground', 'assets/tilemaps/tiles/kenny_ground_64x64.png');
this.load.image('items', 'assets/tilemaps/tiles/kenny_items_64x64.png');
this.load.image('platformer', 'assets/tilemaps/tiles/kenny_platformer_64x64.png');
this.load.tilemapTiledJSON('map', 'assets/tilemaps/maps/multi-tileset.json');
}
Создание тайловой карты и связывание тайлсетов
В методе create() мы создаем объект тайловой карты с помощью this.make.tilemap(). Ключевой этап — это связывание загруженных в память изображений с именами тайлсетов, которые были заданы в редакторе Tiled. Для этого используется метод map.addTilesetImage(). Первым аргументом передается имя тайлсета из файла карты (Tiled), вторым — ключ загруженного изображения в Phaser.
create()
{
var map = this.make.tilemap({ key: 'map' });
var groundTiles = map.addTilesetImage('kenny_ground_64x64', 'ground');
var itemTiles = map.addTilesetImage('kenny_items_64x64', 'items');
var platformTiles = map.addTilesetImage('kenny_platformer_64x64', 'platformer');
}
В результате groundTiles, itemTiles и platformTiles становятся объектами, которые Phaser может использовать для отрисовки соответствующей части карты.
Создание слоя с несколькими тайлсетами
Phaser позволяет использовать несколько тайлсетов для одного слоя карты. Это особенно удобно, когда вы хотите создать сложный слой, состоящий из тайлов разных тематик (например, земля, предметы и платформы). Для этого методу map.createLayer() вторым аргументом нужно передать массив объектов тайлсетов, созданных на предыдущем шаге.
// To use multiple tilesets in a single layer, pass them in an array like this:
map.createLayer('Tile Layer 1', [ groundTiles, itemTiles, platformTiles ]);
Альтернативный способ — передать массив строк с именами тайлсетов (как они указаны в Tiled). Phaser самостоятельно найдет ранее созданные связанные объекты.
// Or you can pass an array of strings, where they = the Tileset name
// map.createLayer('Tile Layer 1', [ 'kenny_ground_64x64', 'kenny_items_64x64', 'kenny_platformer_64x64' ]);
Настройка камеры и элементов управления
Поскольку тайловая карта может быть больше, чем игровое окно, необходимо настроить камеру и управление для ее прокрутки. Метод this.cameras.main.setBounds() устанавливает границы, за которые камера не может выйти, совпадающие с размерами карты в пикселях.
this.cameras.main.setBounds(0, 0, map.widthInPixels, map.heightInPixels);
Для управления камерой создается экземпляр Phaser.Cameras.Controls.FixedKeyControl. Он связывает стрелки на клавиатуре с перемещением камеры с заданной скоростью.
var cursors = this.input.keyboard.createCursorKeys();
var 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);
Также создается текстовый элемент с подсказкой. Важно вызвать для него help.setScrollFactor(0), чтобы текст оставался фиксированным на экране и не двигался вместе с камерой.
Обновление состояния управления
Для того чтобы управление камерой работало, необходимо в каждом кадре обновлять состояние контролов. Это делается в методе update(), который автоматически вызывается игровым циклом Phaser.
update(time, delta)
{
this.controls.update(delta);
}
Метод this.controls.update(delta) принимает параметр delta (время, прошедшее с предыдущего кадра), что позволяет обеспечить плавное и независимое от частоты кадров движение камеры.
Что попробовать дальше
Использование нескольких тайлсетов в Phaser открывает большие возможности для дизайна уровней, позволяя комбинировать различные графические наборы без создания огромных спрайтшитов. Для экспериментов попробуйте создать в Tiled карту, использующую 4-5 различных тайлсетов, и загрузите ее в Phaser. Исследуйте, как работает отрисовка слоев, если тайлсеты в массиве переданы в разном порядке, или добавьте несколько разных слоев (фон, объекты, декорации), каждый со своим уникальным набором тайлсетов.
