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:
2026-10-24 14:15:02 +02:00
co-authored by Claude Opus 5.5
parent b0586e3061
commit b9d2f1161c
48 changed files with 121 additions and 30 deletions
+44 -17
View File
@@ -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).