- 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.
119 lines
4.0 KiB
JavaScript
119 lines
4.0 KiB
JavaScript
const fs = require('fs');
|
|
const path = require('path');
|
|
|
|
const TILED_DIR = 'assets/tiled';
|
|
const TARGET_MAPS = ['faza1_kmetija.json', 'demo_test.json'];
|
|
const ASSET_DIRS = ['../buildings', '../terrain', '../props']; // Relative to TILED_DIR
|
|
|
|
// 1. Gather Images
|
|
const tiles = []; // ARRAY for Tiled JSON compatibility
|
|
let nextId = 0; // Start ID at 0
|
|
let grassId = null;
|
|
|
|
ASSET_DIRS.forEach(dir => {
|
|
const fullDir = path.join(__dirname, '..', 'assets', dir.replace('../', ''));
|
|
if (fs.existsSync(fullDir)) {
|
|
const files = fs.readdirSync(fullDir);
|
|
files.forEach(file => {
|
|
if (file.endsWith('.png')) {
|
|
const relPath = path.join(dir, file);
|
|
|
|
// Add to array
|
|
tiles.push({
|
|
id: nextId,
|
|
image: relPath,
|
|
imageheight: 64, // Placeholder, Tiled will try to read actual
|
|
imagewidth: 64
|
|
});
|
|
|
|
// Identify Grass
|
|
if (file.includes('grass') || file.includes('resource_pile_food')) { // Fallback
|
|
if (grassId === null) grassId = nextId;
|
|
}
|
|
|
|
nextId++;
|
|
}
|
|
});
|
|
}
|
|
});
|
|
|
|
console.log(`🔍 Found ${tiles.length} assets.`);
|
|
console.log(`🌿 Grass ID: ${grassId}`);
|
|
|
|
// 2. Setup Tileset Object
|
|
const autoTileset = {
|
|
"columns": 0,
|
|
"grid": { "height": 1, "orientation": "orthogonal", "width": 1 },
|
|
"margin": 0,
|
|
"name": "Auto_Assets",
|
|
"spacing": 0,
|
|
"tilecount": tiles.length,
|
|
"tileheight": 256,
|
|
"tiles": tiles, // Array!
|
|
"tilewidth": 256,
|
|
"type": "tileset_image_collection"
|
|
};
|
|
|
|
// 3. Process Maps
|
|
TARGET_MAPS.forEach(mapFile => {
|
|
const mapPath = path.join(TILED_DIR, mapFile);
|
|
if (!fs.existsSync(mapPath)) {
|
|
console.warn(`⚠️ Map not found: ${mapPath}`);
|
|
return;
|
|
}
|
|
|
|
try {
|
|
const mapData = JSON.parse(fs.readFileSync(mapPath, 'utf8'));
|
|
|
|
// A. Inject Tileset
|
|
mapData.tilesets = [autoTileset];
|
|
|
|
// B. Auto-Ground (Fill Layer 1 with Grass)
|
|
const mapWidth = 100;
|
|
const mapHeight = 100;
|
|
mapData.width = mapWidth;
|
|
mapData.height = mapHeight;
|
|
|
|
// Find Ground Layer
|
|
const groundLayer = mapData.layers.find(l => l.name === 'Ground');
|
|
if (groundLayer && grassId !== null) {
|
|
groundLayer.width = mapWidth;
|
|
groundLayer.height = mapHeight;
|
|
groundLayer.data = new Array(mapWidth * mapHeight).fill(grassId + 1); // +1 because GID is local ID + firstgid (1)
|
|
// Wait, for image collections, keys match the ID.
|
|
// But map data uses GID (Global Tile ID).
|
|
// If firstgid is 1 (default for first tileset), then tile with ID 0 is GID 1.
|
|
// So tile with ID X is GID X + 1.
|
|
console.log(`✅ Filled Ground in ${mapFile} with GID ${grassId + 1}`);
|
|
}
|
|
|
|
// C. Demo Setup (Landmarks)
|
|
if (mapFile === 'demo_test.json') {
|
|
const objectLayer = mapData.layers.find(l => l.name === 'Objects');
|
|
if (objectLayer) {
|
|
objectLayer.width = mapWidth;
|
|
objectLayer.height = mapHeight;
|
|
// Add 5 random buildings
|
|
const randomIds = tiles.slice(0, 5).map(t => t.id);
|
|
const objData = new Array(mapWidth * mapHeight).fill(0);
|
|
|
|
randomIds.forEach((tileId, index) => {
|
|
const x = 10 + (index * 10);
|
|
const y = 15;
|
|
const idx = y * mapWidth + x;
|
|
if (idx < objData.length) objData[idx] = tileId + 1; // +1 GID
|
|
});
|
|
objectLayer.data = objData;
|
|
console.log(`✅ Placed 5 landmarks in ${mapFile}`);
|
|
}
|
|
}
|
|
|
|
// Save
|
|
fs.writeFileSync(mapPath, JSON.stringify(mapData, null, 4));
|
|
console.log(`💾 Saved updated ${mapFile}`);
|
|
|
|
} catch (e) {
|
|
console.error(`❌ Error processing ${mapFile}:`, e);
|
|
}
|
|
});
|