Mappa a gradini con le miniature; Campomigliaio dalle foto dell'Arcu; Marco Arcuri nei crediti
- la mappa: una scheda per posto con la miniatura del suo sfondo e il nome, in quattro fasce come il paese a gradini, le strade disegnate fra le schede; sta in una schermata sul desktop - tools/miniature.py (make miniature): le miniature 128x72 a 64 colori in assets/scenes/mini/ - tre sfondi di Campomigliaio generati da Codex dalle foto di Marco Arcuri (ponte, Circolo SMS, strada), pronti a 640x360 ma non ancora collegati - Marco Arcuri «l'Arcu» nei crediti, fra le fotografie Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ApqNBvNbNCwXqR2RLo8QJh
This commit is contained in:
+44
-17
@@ -88,29 +88,56 @@ for (const b of document.querySelectorAll('.open-credits')) b.addEventListener('
|
||||
$('close-credits').addEventListener('click', () => { $('credits').hidden = true; });
|
||||
|
||||
// --- Mappa: i posti visti e le strade fra loro; un clic su un posto ci porta (game.travel).
|
||||
// La mappa: i posti visti come schede con la miniatura, a gradini come il paese (le quattro fasce della pianta,
|
||||
// dalla Fortezza ai campi), e in ogni gradino da sinistra a destra. Le strade si disegnano dopo, fra le schede.
|
||||
const MAP_BANDS = [25, 50, 75, Infinity];
|
||||
function openMap() {
|
||||
if (!running || game.dialogue) return;
|
||||
const board = $('map-board'), svg = $('map-roads'), places = game.mapPlaces(), at = Object.fromEntries(places.map(p => [p.id, p.at]));
|
||||
svg.replaceChildren(...game.mapRoads().map(([a, b]) => {
|
||||
const line = document.createElementNS('http://www.w3.org/2000/svg', 'line');
|
||||
[['x1', at[a][0]], ['y1', at[a][1]], ['x2', at[b][0]], ['y2', at[b][1]]].forEach(([k, v]) => line.setAttribute(k, v));
|
||||
return line;
|
||||
}));
|
||||
board.replaceChildren(svg, ...places.map(p => {
|
||||
const b = document.createElement('button');
|
||||
b.type = 'button';
|
||||
b.dataset.scene = p.id;
|
||||
b.textContent = p.name;
|
||||
b.classList.toggle('here', p.here);
|
||||
b.style.left = p.at[0] + '%';
|
||||
b.style.top = p.at[1] + '%';
|
||||
b.addEventListener('click', () => { if (game.travel(p.id)) $('map').hidden = true; });
|
||||
return b;
|
||||
const board = $('map-board'), svg = $('map-roads'), places = game.mapPlaces();
|
||||
const bands = MAP_BANDS.map(() => []);
|
||||
for (const p of places) bands[MAP_BANDS.findIndex(top => p.at[1] < top)].push(p);
|
||||
board.replaceChildren(svg, ...bands.filter(b => b.length).map(band => {
|
||||
const row = document.createElement('div');
|
||||
row.className = 'map-band';
|
||||
row.append(...band.sort((a, b) => a.at[0] - b.at[0]).map(p => {
|
||||
const b = document.createElement('button');
|
||||
b.type = 'button';
|
||||
b.dataset.scene = p.id;
|
||||
b.title = p.name;
|
||||
b.classList.toggle('here', p.here);
|
||||
const img = document.createElement('img');
|
||||
img.alt = '';
|
||||
if (p.mini) img.src = p.mini;
|
||||
const name = document.createElement('span');
|
||||
name.textContent = p.name;
|
||||
b.append(img, name);
|
||||
b.addEventListener('click', () => { if (game.travel(p.id)) $('map').hidden = true; });
|
||||
return b;
|
||||
}));
|
||||
return row;
|
||||
}));
|
||||
$('map').hidden = false;
|
||||
// Sul telefono la pianta scorre: si parte col posto dove si è, al centro.
|
||||
drawRoads();
|
||||
// Sul telefono la mappa scorre: si parte col posto dove si è, al centro.
|
||||
board.querySelector('.here')?.scrollIntoView({ block: 'center', inline: 'center' });
|
||||
}
|
||||
// Le strade fra le schede, misurate dopo l'impaginazione (e di nuovo se la finestra cambia misura).
|
||||
function drawRoads() {
|
||||
const board = $('map-board'), svg = $('map-roads'), origin = board.getBoundingClientRect();
|
||||
const center = id => {
|
||||
const r = board.querySelector(`[data-scene="${id}"] img`)?.getBoundingClientRect();
|
||||
return r && [r.left + r.width / 2 - origin.left, r.top + r.height / 2 - origin.top];
|
||||
};
|
||||
svg.setAttribute('viewBox', `0 0 ${board.scrollWidth} ${board.scrollHeight}`);
|
||||
svg.style.width = board.scrollWidth + 'px';
|
||||
svg.style.height = board.scrollHeight + 'px';
|
||||
svg.replaceChildren(...game.mapRoads().map(([a, b]) => [center(a), center(b)]).filter(([a, b]) => a && b).map(([a, b]) => {
|
||||
const line = document.createElementNS('http://www.w3.org/2000/svg', 'line');
|
||||
[['x1', a[0]], ['y1', a[1]], ['x2', b[0]], ['y2', b[1]]].forEach(([k, v]) => line.setAttribute(k, v));
|
||||
return line;
|
||||
}));
|
||||
}
|
||||
addEventListener('resize', () => { if (!$('map').hidden) drawRoads(); });
|
||||
$('map-button').addEventListener('click', openMap);
|
||||
|
||||
// --- «?»: per qualche secondo si vede tutto quello che si può toccare (sul telefono non c'è il mouse da passarci sopra).
|
||||
|
||||
Reference in New Issue
Block a user