Files
novafarma/tools/tmx_to_json.js
David Kotnik 7264ec6fc0 feat: complete Style 32 overhaul & Tiled integration fix
- Enforced 'Style 32 - Dark Chibi Vector' for all ground assets.
- Fixed critical Prologue-to-Game crash (function renaming).
- Implemented Tiled JSON/TMX auto-conversion.
- Updated Asset Manager to visualize 1800+ assets.
- Cleaned up project structure (new assets/grounds folder).
- Auto-Ground logic added to GameScene.js.
2026-01-11 20:08:56 +01:00

121 lines
3.9 KiB
JavaScript

const fs = require('fs');
const path = require('path');
const src = 'assets/tiled/ProbnaFarma.tmx';
const dest = 'assets/maps/NovaFarma.json';
try {
const xml = fs.readFileSync(src, 'utf8');
// Super simple Regex parser for Tiled TMX (Caveat: Fragile!)
const parseAttr = (tag, attr) => {
const match = tag.match(new RegExp(`${attr}="([^"]*)"`));
return match ? match[1] : null;
};
// Extract Map Info
const mapMatch = xml.match(/<map [^>]+>/);
if (!mapMatch) throw new Error("No <map> tag");
const mapTag = mapMatch[0];
const width = parseInt(parseAttr(mapTag, 'width'));
const height = parseInt(parseAttr(mapTag, 'height'));
const tilewidth = parseInt(parseAttr(mapTag, 'tilewidth'));
const tileheight = parseInt(parseAttr(mapTag, 'tileheight'));
const json = {
width, height, tilewidth, tileheight,
layers: [],
tilesets: [],
orientation: "orthogonal",
renderorder: "right-down",
type: "map"
};
// Extract Layers
const layerRegex = /<layer [^>]+>([\s\S]*?)<\/layer>/g;
let layerMatch;
let idCounter = 1;
while ((layerMatch = layerRegex.exec(xml)) !== null) {
const fullLayer = layerMatch[0];
const content = layerMatch[1];
const openTag = fullLayer.match(/<layer [^>]+>/)[0];
const name = parseAttr(openTag, 'name');
const visible = parseAttr(openTag, 'visible') !== '0';
let data = [];
// Extract CSV Data
const dataMatch = content.match(/<data encoding="csv">([\s\S]*?)<\/data>/);
if (dataMatch) {
data = dataMatch[1].replace(/\s/g, '').split(',').map(Number);
}
json.layers.push({
id: idCounter++,
name: name,
type: "tilelayer",
width: width,
height: height,
visible: visible,
opacity: 1,
x: 0, y: 0,
data: data
});
}
// Extract Object Groups
const objGroupRegex = /<objectgroup [^>]+>([\s\S]*?)<\/objectgroup>/g;
while ((layerMatch = objGroupRegex.exec(xml)) !== null) {
const openTag = layerMatch[0].match(/<objectgroup [^>]+>/)[0];
const name = parseAttr(openTag, 'name');
json.layers.push({
id: idCounter++,
name: name,
type: "objectgroup",
visible: true,
opacity: 1,
objects: [] // Parsing objects is harder, skipping for now as user just wants visuals mostly
});
}
// Extract Tilesets
// <tileset firstgid="1" source="Buildings.tsx"/>
const tilesetRegex = /<tileset [^>]+>/g;
let tsMatch;
while ((tsMatch = tilesetRegex.exec(xml)) !== null) {
const tsTag = tsMatch[0];
const firstgid = parseInt(parseAttr(tsTag, 'firstgid'));
const source = parseAttr(tsTag, 'source');
// We need to bake the tileset data or link it.
// Phaser supports linked tilesets if JSON.
// But for simplicity, let's create a minimal embedded definition referring to image collection
// Actually, Tiled JSON exports 'source' usually.
// Fix path: TMX is in assets/tiled/, references are relative.
// JSON is in assets/maps/.
// If source is "Buildings.tsx", in TMX it means "assets/tiled/Buildings.tsx".
// In JSON (assets/maps), it should be "../tiled/Buildings.tsx".
let jsonSource = source;
if (!source.includes('/')) jsonSource = '../tiled/' + source;
json.tilesets.push({
firstgid: firstgid,
source: jsonSource
});
}
// Write
fs.writeFileSync(dest, JSON.stringify(json, null, 4));
console.log(`✅ Converted TMX to JSON: ${dest}`);
} catch (e) {
console.error("❌ Conversion failed:", e);
// Create Dummy
fs.writeFileSync(dest, JSON.stringify({ width: 10, height: 10, layers: [] }));
}