SOULGATE/client/js/tiledLoader.js
2026-05-04 03:42:47 +02:00

96 lines
3.2 KiB
JavaScript

// tiledLoader.js : charge une map Tiled (.tmj + .tsx) et la dessine en iso
import { Sprite, Assets } from 'pixi.js';
import { iso, getTw, getTh } from './renderer.js';
export async function loadTiledMap(mapPath) {
// baseUrl = dossier du .tmj (les .tsx sont a cote)
const baseUrl = mapPath.substring(0, mapPath.lastIndexOf('/') + 1);
const map = await fetch(mapPath).then(r => r.json());
// parse les .tsx (XML) referencements (firstgid + chemin image par tile id)
const tilesets = [];
for (const ts of map.tilesets) {
const tsxText = await fetch(baseUrl + ts.source).then(r => r.text());
const xml = new DOMParser().parseFromString(tsxText, 'text/xml');
const tiles = {};
for (const tile of xml.querySelectorAll('tile')) {
const id = parseInt(tile.getAttribute('id'));
const img = tile.querySelector('image');
if (img) {
tiles[id] = {
src: baseUrl + img.getAttribute('source'),
w: parseInt(img.getAttribute('width')),
h: parseInt(img.getAttribute('height')),
};
}
}
tilesets.push({ firstgid: ts.firstgid, tiles });
}
// precharger toutes les textures
const urls = [];
for (const ts of tilesets) {
for (const id in ts.tiles) urls.push(ts.tiles[id].src);
}
await Assets.load(urls);
return { map, tilesets };
}
function _gidToTile(gid, tilesets) {
// chercher dans le bon tileset (firstgid descendant)
for (let i = tilesets.length - 1; i >= 0; i--) {
if (gid >= tilesets[i].firstgid) {
return tilesets[i].tiles[gid - tilesets[i].firstgid] || null;
}
}
return null;
}
export function drawTiledMap(layer, data) {
const { map, tilesets } = data;
const W = map.width;
const H = map.height;
const tw = getTw();
const th = getTh();
// reference : la base (footprint iso) d'un sprite Kenney fait 256x128 px
// au tw courant, on veut que cette base remplisse 1 unite monde (tw x th px)
const REF_TILE_W = 256;
const scale = tw / REF_TILE_W;
for (const tlayer of map.layers) {
if (tlayer.type !== 'tilelayer') continue;
if (tlayer.visible === false) continue;
for (let i = 0; i < tlayer.data.length; i++) {
const gid = tlayer.data[i];
if (gid === 0) continue; // 0 = case vide
const tile = _gidToTile(gid, tilesets);
if (!tile) continue;
const col = i % W;
const row = Math.floor(i / W);
// centrer la map sur (0, 0)
const wx = col - (W - 1) / 2;
const wy = row - (H - 1) / 2;
const tex = Assets.get(tile.src);
if (!tex) continue;
const sprite = new Sprite(tex);
sprite.anchor.set(0.5, 1.0); // base centree sur la tile, le sprite "monte"
const p = iso(wx, wy);
sprite.x = p.x;
sprite.y = p.y + th / 2; // decalage half pour que la pointe basse de la diamond touche la base
sprite.scale.set(scale);
layer.addChild(sprite);
}
}
}