Atualize automaticamente o Tileset embutido do seu mapa no Tiled com um script Node.js.
Escrito em 2 de outubro de 2021 - 🕒 3 min. de leituraCriar mapas com o Tiled é ótimo e da pra usá-los em praticamente qualquer game engine, incluindo a minha favorita, Phaser JS 😊
Para carregar um mapa com Phaser JS é bem simples, primeiro, você carrega todos os arquivos na função preload
, depois cria um novo mapa com a função this.make.tilemap()
e pronto. Veja abaixo um snippet de código do blog Ourcade:
preload()
{
// load the PNG file
this.load.image('base_tiles', 'assets/base_tiles.png')
// load the JSON file
this.load.tilemapTiledJSON('tilemap', 'assets/base_tiles.json')
}
create()
{
// create the Tilemap
const map = this.make.tilemap({ key: 'tilemap' })
// add the tileset image we are using
const tileset = map.addTilesetImage('standard_tiles', 'base_tiles')
// create the layers we want in the right order
map.createStaticLayer('Background', tileset)
}
Mas, infelizmente, nem tudo é perfeito, pois, para que isso funcione, você precisa que o seu tileset
esteja embutido no mapa do Tiled.
O problema com isso é que quando você tem muitos mapas, cada um deles terá sua própria versão do tileset
, então caso qualquer alteração seja feita em um deles, todos os outros mapas ficarão desatualizados.
Na verdade, eu já meio que falei sobre isso neste blog há um ano atrás, no meu Game Devlog #7, mas essa solução foi embutir programaticamente um tileset
externo em um mapa do Tiled, hoje eu vou pegar um tileset
que já está embutido em um mapa e copiá-lo para todos os meus outros mapas, vamos ver como.
O código
Meu script recebera um parâmetro com o nome do mapa de onde o tileset
precisa ser copiado, e o objetivo é executar o script usando node copy-tileset-data.js nomeDoArquivoDoMapa
.
Primeiro, vou importar todas as funções necessárias do package fs
e declarar o meu diretório de mapas com path.resolve
:
const { readdirSync, readFileSync, writeFileSync } = require('fs');
const path = require('path');
const TILESETS_PATH = path.resolve(
__dirname,
'..',
'content',
'assets',
'sprites',
'maps'
);
// Call the function with the script parameter
copyTilesetData(process.argv[2]);
async function copyTilesetData(tilesetName = null) {
// TODO
}
Agora, para a função copyTilesetData
, vou percorrer todas as minhas pastas de mapas (maps_dir_1
, maps_dir_2
, etc) e procurar o mapa com o tileset
que quero, e quando achar, vou carregar o arquivo JSON
com a função readFileSync
e salvar o atributo tilesets
em uma variável local para usar mais tarde.
Em seguida farei um loop nos outros mapas para carregar o tileset
que salvei antes neles, e em seguida, salvar essas alterações nos arquivos com o writeFileSync
.
async function copyTilesetData(tilesetName = null) {
if (!tilesetName) {
console.error('No Tileset passed');
return;
}
const allFiles = [];
let sourceTilesetData = [];
// eslint-disable-next-line no-restricted-syntax
for (const tilesetPath of ['maps_dir_1', 'maps_dir_2']) {
const filePath = path.resolve(TILESETS_PATH, tilesetPath);
// eslint-disable-next-line no-await-in-loop
const spritesFiles = readdirSync(filePath);
// eslint-disable-next-line no-restricted-syntax
for (const spritesFile of spritesFiles) {
if (spritesFile === `${tilesetName}.json`) {
// eslint-disable-next-line no-await-in-loop
const jsonData = JSON.parse(await readFileSync(path.resolve(filePath, spritesFile)));
sourceTilesetData = jsonData.tilesets;
} else {
allFiles.push(path.resolve(filePath, spritesFile));
}
}
}
// eslint-disable-next-line no-restricted-syntax
for (const jsonFile of allFiles) {
// eslint-disable-next-line no-await-in-loop
const jsonData = JSON.parse(await readFileSync(
jsonFile
));
jsonData.tilesets = sourceTilesetData;
// eslint-disable-next-line no-await-in-loop
await writeFileSync(
jsonFile,
JSON.stringify(jsonData, null, 2)
);
}
}
E é isso! Espero que este script ajude bastante você do mesmo jeito que me ajuda. Até a próxima galera!
Tags:
Posts relacionados
Publicar um comentário
Comentários
Nenhum comentário.