О чем этот пример
Создание больших тайловых карт с использованием множественных атласов (Multiatlas) в Phaser позволяет эффективно управлять графикой и оптимизировать производительность вашей игры. Этот подход особенно полезен для генерации процедурных миров, случайного заполнения пространства и работы с большим количеством спрайтов. В статье мы разберем, как загружать multiatlas, получать кадры и использовать их для создания динамической tilemap.
Версия 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.setPath('assets/loader-tests/');
// this.load.multiatlas('megaset', 'texture-packer-multi-atlas.json');
this.load.multiatlas('megaset', 'assets/loader-tests/texture-packer-multi-atlas.json', 'assets/loader-tests/');
}
create ()
{
const atlasTexture = this.textures.get('megaset');
const frames = atlasTexture.getFrameNames();
const firstFrame = this.textures.getFrame('megaset', frames[20]);
const rows = 1024;
const cols = 768;
const tileSize = 256;
this.tileMap = this.make.tilemap({ tileWidth: tileSize, tileHeight: firstFrame.height, width: rows, height: cols });
const tileset = this.tileMap.addTilesetImage('megaset');
const layer = this.tileMap.createBlankLayer('layer1', tileset);
layer.forEachTile(tile => {
const randomIndex = Math.floor(Math.random() * frames.length);
tile.index = randomIndex;
});
console.log(this.tileMap.tilesets);
// for (let i = 0; i < frames.length; i++)
// {
// const x = Phaser.Math.Between(0, 1024);
// const y = Phaser.Math.Between(0, 768);
// this.add.image(x, y, 'megaset', frames[ i ]);
// }
}
}
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
backgroundColor: '#2d2d2d',
parent: 'phaser-example',
pixelArt: true,
scene: Example
};
const game = new Phaser.Game(config);
Загрузка multiatlas в Phaser
Multiatlas — это формат, который позволяет разбивать один большой атлас на несколько файлов изображений, что удобно для управления памятью и загрузки. В Phaser для этого используется метод load.multiatlas. В примере мы загружаем атлас с ключом 'megaset' из JSON-файла и указываем путь к папке с изображениями.
this.load.multiatlas('megaset', 'assets/loader-tests/texture-packer-multi-atlas.json', 'assets/loader-tests/');
Здесь первый аргумент — ключ для доступа к атласу, второй — путь к JSON-файлу с описанием кадров, третий — базовый путь к изображениям. После загрузки атлас становится доступен через текстуры сцены.
Получение кадров из загруженного атласа
После загрузки multiatlas мы можем получить доступ к его кадрам (frames) для использования в тайловой карте. Для этого используем методы this.textures.get и this.textures.getFrameNames.
const atlasTexture = this.textures.get('megaset');
const frames = atlasTexture.getFrameNames();
const firstFrame = this.textures.getFrame('megaset', frames[20]);
atlasTexture — это объект текстуры атласа. frames — массив имен всех кадров в атласе. firstFrame — пример получения конкретного кадра по индексу (в данном случае 20), чтобы узнать его высоту для настройки tilemap. Это полезно, если кадры имеют разный размер.
Создание и заполнение tilemap
Tilemap в Phaser позволяет эффективно отрисовывать большие области с повторяющимися тайлами. В примере мы создаем пустую тайловую карту большого размера и заполняем ее случайными кадрами из multiatlas.
const rows = 1024;
const cols = 768;
const tileSize = 256;
this.tileMap = this.make.tilemap({ tileWidth: tileSize, tileHeight: firstFrame.height, width: rows, height: cols });
const tileset = this.tileMap.addTilesetImage('megaset');
const layer = this.tileMap.createBlankLayer('layer1', tileset);
layer.forEachTile(tile => {
const randomIndex = Math.floor(Math.random() * frames.length);
tile.index = randomIndex;
});
make.tilemap создает тайловую карту с указанными параметрами: ширина и высота тайла, общее количество строк и столбцов. addTilesetImage связывает атлас 'megaset' с тайловой картой. createBlankLayer создает слой, а forEachTile проходит по всем тайлам и присваивает каждому случайный индекс из массива кадров. Это позволяет быстро сгенерировать разнообразный ландшафт.
Особенности работы с индексами и кадрами
При использовании multiatlas в tilemap важно понимать, как индексы тайлов соответствуют кадрам в атласе. Каждый кадр в multiatlas имеет свой порядковый номер, который используется как индекс в тайловой карте.
console.log(this.tileMap.tilesets);
Этот выведет в консоль информацию о tileset, включая соответствие индексов и кадров. Убедитесь, что индексы не выходят за пределы количества кадров в атласе, чтобы избежать ошибок отрисовки. В примере случайный индекс генерируется в диапазоне от 0 до frames.length - 1, что гарантирует корректность.
Что попробовать дальше
Использование multiatlas для создания tilemap в Phaser — мощный инструмент для оптимизации графики и генерации процедурного контента. Вы можете экспериментировать с разными размерами тайлов, комбинировать несколько атласов или добавлять анимацию к тайлам. Попробуйте изменить логику заполнения карты, например, использовать шум Перлина для более естественного распределения или добавлять слои для разных типов местности.
