Importando arquivo de tileset externo no Phaser JS com Webpack - Skate Platformer Game Devlog #07
Escrito em 8 de outubro de 2020 - 🕒 4 min. de leituraNo Game Devlog de hoje, vou mostrar como importar tilesets externos no Phaser JS, mas primeiro vamos tirar isso do caminho: Esqueça o nome "Skate Platformer", o nome do nosso jogo vai ser Super Ollie vs Pebble Corp. A gente não planejava dar um nome ao jogo agora, mas a ideia simplesmente veio nas nossas cabeças e achamos que o nome é perfeito. Deixa eu te perguntar uma coisa, qual é o pior inimigo do skatista? Indiscutivelmente essas pequenas pedrinhas, certo? E se no futuro houver uma empresa do mal que quer proibir o skate em todos os lugares, como essa empresa se chamaria? Pebble Corp, é claro. Pebble é o nome em inglês daquelas pedrinhas que geralmente você encontra em praias e tal. Agora com isso fora do caminho, vamos continuar com o post.
Importando tilesets externos
Tiled é uma ferramenta open source poderosa para construir mapas 2D suportados por muitas engines de jogos diferentes, incluindo Phaser JS, que é o framework que eu estou usando para esse jogo.
Há um pequeno problema, ao carregar mapas do Tiled no Phaser JS, o tileset precisa estar “embutido” no mapa, caso contrário, o Phaser JS não consegue carregá-lo. Isso é muito frustrante porque sempre que eu faço alterações em um tileset, eu tenho que ir em todos os meus arquivos de mapa e “reembutir” o tileset, isso acaba demorando muito se o projeto tiver muitos mapas e tilesets diferentes.
Para resolver este problema, decidi encontrar uma solução para embutir automaticamente os tilesets com o Webpack. Para fazer isso, comparei o arquivo JSON do mesmo mapa antes e depois de embutir um tileset, e ficou assim:
Como você pode ver, em vez de ter a propriedade source
apontando para um arquivo externo, tipo "source": "../tilesets/test_tileset.json"
, ele contém todo o conteúdo desse arquivo mais um atributo firstgid
, então tudo o que eu preciso fazer é percorrer todos os mapas do Tiled, ler a propriedade tilesets
, carregar cada arquivo tileset e colocar o seu conteúdo em uma nova array na propriedade tilesets
.
Foi assim que eu fiz:
const CopyWebpackPlugin = require('copy-webpack-plugin');
const { promises: fs } = require('fs');
const stageFiles = await fs.readdir(STAGES_PATH);
// get only the JSON files
const stageJsons = stageFiles
.filter((stage) => stage.split('.')[1] === 'json');
const copyWebpackPluginPatterns = [];
stageJsons.forEach((stage) => {
copyWebpackPluginPatterns.push({
from: `${STAGES_PATH}/${stage}`,
to: '../assets/stages',
transform: (fileBuffer, elPath) => {
const manifestString = fileBuffer.toString();
const stageData = JSON.parse(manifestString);
const newTilesets = stageData.tilesets.map((tileset) => {
// firstgid is an important id reference for Tiled
const { firstgid } = tileset;
if (!tileset.source) {
// if there's no source, it means the Tileset
// is already embedded
return tileset;
}
// on my setup, stages are in root/stages/
// and the tilesets are in root/tilesets/
// so we need to remove "../tilesets/" from the path
// and load it based on the root dir of the tilesets
const filePath = tileset.source.replace('../tilesets/', '');
// eslint-disable-next-line import/no-dynamic-require
const tilesetData = require(`${TILESETS_PATH}/${filePath}`);
if (!tilesetData) {
console.error('Could not find file', `${TILESETS_PATH}/${filePath}`);
return tileset;
}
return {
...tilesetData,
firstgid,
};
});
stageData.tilesets = newTilesets;
return Buffer.from(JSON.stringify(stageData));
},
});
});
module.exports = {
plugins: [
new CopyWebpackPlugin({
patterns: [
...copyWebpackPluginPatterns,
],
}),
],
};
Como você pode ver, precisamos do plugin copy-webpack-plugin
para fazê-lo funcionar, copiando todos os mapas do diretório assets/stages
para o diretório dist/assets/stages
, e ao copiá-lo, definimos uma função transform
que carregará os tilesets externos e os embutirá nos mapas Tiled. Adicione este código ao seu arquivo de configuração do Webpack se quiser obter o mesmo resultado.
Criando a tela inicial
Isso foi realmente muito fácil e direto, especialmente porque é praticamente o mesmo código do Game Devlog anterior.
Primeiro eu carrego o mapa na função create
:
const map = scene.make.tilemap({ key: 'title_screen' });
const tileset = map.addTilesetImage('title_screen', 'city_tileset');
const { width, height } = this.cameras.main;
const background = map.createDynamicLayer('background', tileset, 0, 0);
const ground = map.createDynamicLayer('ground', tileset, 0, 0);
const foreground = map.createDynamicLayer('foreground', tileset, 0, 0);
[background, ground, foreground]
.forEach((dynamicLayer) => {
dynamicLayer.setY(
height - background.height
);
// set this property to make the the layers move in different speeds
dynamicLayer.setScrollFactor(dynamicLayer.parallaxSpeedX);
});
// we're going to use that in the update function
this.parallaxCounter = 0;
Agora tudo o que fiz foi mover a câmera até a posição y = 640
e, quando ela chegar lá, mudar a posição de volta paray = 0
, e repetir isso indefinidamente.
this.parallaxCounter += 1;
if (this.parallaxCounter === 640) {
this.parallaxCounter = 0;
}
this.cameras.main.scrollX = this.parallaxCounter;
E por hoje é isso! Espero que tenha gostado, se quiser, deixe um comentário e considere se inscrever no meu canal no YouTube.
Tags:
- programação
- jogos
- javascript
- phaser
- phaser 3
- game devlog
- gamedev
- skate platformer
- super ollie vs pebble corp
- webpack
- tiled
Posts relacionados
Publicar um comentário
Comentários
Nenhum comentário.