О чем этот пример
Часто в 2D-играх на тайловых картах нужно, чтобы некоторые элементы вели себя как независимые объекты — например, монеты, которые можно собрать, или препятствия, которые можно разрушить. Вручную создавать спрайты для каждого такого тайла — долго и неэффективно. В этой статье мы разберем метод `createFromTiles`, который позволяет автоматически конвертировать выбранные тайлы карты в полноценные спрайты Phaser. Это мощный инструмент для быстрого прототипирования и создания динамических игровых миров, где часть окружения должна реагировать на действия игрока.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.spritesheet('fantasy-tiles', 'assets/tilemaps/tiles/fantasy-tiles.png', { frameWidth: 64 });
this.load.tilemapTiledJSON('map', 'assets/tilemaps/maps/create from tiles.json');
}
create ()
{
const map = this.add.tilemap('map');
const tiles = map.addTilesetImage('fantasy-tiles');
const layer = map.createLayer('Tile Layer 1', tiles);
// Because we have loaded the tileset as a spritesheet, we can set the
// 'useSpriteSheet' property to set the texture and frame when creating the sprites.
// If you have loaded the tileset as an image, then this will not work and you
// should set the texture and frame manually after creating the sprites.
const sprites = map.createFromTiles([ 53, 50 ], -1, { useSpriteSheet: true });
// Bounce the sprites just to show they're no longer tiles:
this.tweens.add({
targets: sprites,
y: '-=32',
duration: 1000,
ease: 'Sine.easeInOut',
yoyo: true,
repeat: -1
});
}
}
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
backgroundColor: '#00000',
parent: 'phaser-example',
pixelArt: true,
scene: Example
};
const game = new Phaser.Game(config);
Загрузка ресурсов и подготовка карты
Как и в большинстве примеров с Phaser, работа начинается с метода preload, где мы загружаем необходимые ассеты. Ключевой момент — тайлсет загружается не как обычное изображение, а как спрайтшит (spritesheet). Это означает, что мы указываем размер одного кадра (тайла), и Phaser автоматически разбивает изображение на отдельные фреймы.
this.load.spritesheet('fantasy-tiles', 'assets/tilemaps/tiles/fantasy-tiles.png', { frameWidth: 64 });
this.load.tilemapTiledJSON('map', 'assets/tilemaps/maps/create from tiles.json');
Также загружается сама тайловая карта в формате JSON, экспортированная из редактора Tiled. В методе create мы создаем объект карты, добавляем к ней загруженный тайлсет и создаем слой для отрисовки.
const map = this.add.tilemap('map');
const tiles = map.addTilesetImage('fantasy-tiles');
const layer = map.createLayer('Tile Layer 1', tiles);
На этом этапе карта отображается как статичное изображение. Все ее элементы — это просто части одного большого холста (тайлового слоя).
Волшебный метод createFromTiles
Сердце примера — вызов метода map.createFromTiles. Его задача — найти на карте все тайлы с указанными индексами, удалить их с тайлового слоя и создать на их месте отдельные игровые объекты (спрайты).
const sprites = map.createFromTiles([ 53, 50 ], -1, { useSpriteSheet: true });
Давайте разберем аргументы:
1. **Первый аргумент ([53, 50])** — это массив индексов тайлов, которые мы хотим преобразовать. Индекс соответствует номеру тайла в тайлсете. В нашем случае мы ищем тайлы с номерами 53 и 50.
2. **Второй аргумент (-1)** — это индекс, на который нужно заменить оригинальный тайл *на карте* после создания спрайта. Значение -1 означает "удалить тайл", то есть оставить на его месте пустоту. Если бы мы указали, например, `0`, то на месте каждого найденного тайла появился бы тайл с индексом 0.
3. **Третий аргумент ({ useSpriteSheet: true })** — это ключевая опция. Она говорит Phaser: "Мы загрузили тайлсет как спрайтшит, поэтому для каждого созданного спрайта автоматически задай текстуру и кадр (frame), соответствующие оригинальному тайлу". Без этой опции спрайты создались бы с пустой текстурой.
Работа со спрайтами после создания
Метод createFromTiles возвращает массив созданных спрайтов. Это обычные объекты Phaser.GameObjects.Sprite, и с ними можно делать все, что угодно: добавлять физические тела, анимации, обрабатывать столкновения.
В примере мы добавляем к ним простую анимацию-покачивание с помощью системы твинов, чтобы наглядно показать, что теперь это — независимые, живые объекты.
this.tweens.add({
targets: sprites,
y: '-=32',
duration: 1000,
ease: 'Sine.easeInOut',
yoyo: true,
repeat: -1
});
Этот твин перемещает все спрайты в массиве sprites на 32 пикселя вверх за 1 секунду, а затем возвращает обратно, создавая эффект плавающего движения. Параметр yoyo: true отвечает за возврат к начальному состоянию, а repeat: -1 делает анимацию бесконечной.
Важные нюансы и ограничения
1. **Спрайтшит против Изображения:** Опция useSpriteSheet: true работает *только* если тайлсет был загружен через load.spritesheet. Если вы загрузили его как обычное изображение (load.image), фреймы не будут созданы, и опция не сработает. В таком случае вам придется вручную задавать текстуру и фрейм для созданных спрайтов в цикле.
2. **Слои и индексы:** Метод работает с конкретным слоем карты. В примере он неявно использует слой, созданный ранее. Индексы тайлов (53, 50) — это их глобальные ID в тайлсете, которые можно увидеть в редакторе Tiled.
3. **Производительность:** Преобразование сотен тайлов в спрайты может негативно сказаться на производительности, так как каждый спрайт — это отдельный объект для отрисовки. Используйте этот метод для относительно небольшого количества динамических объектов.
Что попробовать дальше
Метод createFromTiles — это элегантный мост между статичным миром тайловых карт и динамичным миром игровых объектов Phaser. Он идеально подходит для быстрого создания собираемых предметов, разрушаемых блоков или точек появления врагов прямо на основе данных из Tiled. Для экспериментов попробуйте: преобразовать тайлы в спрайты с физическим телом (this.physics.add.sprite), чтобы они падали; использовать разные индексы для замены (вместо -1) и создать эффект "сбора" с анимацией исчезновения; или привязать к созданным спрайтам пользовательские данные (custom properties из Tiled) для управления их поведением.
