Mappa del paese per spostarsi veloci; Codex nei crediti

Il pulsante «Mappa» (o il tasto P) apre la pianta del paese a gradini: ci sono i posti già visti,
le strade sono le uscite fra loro, un clic porta lì (game.travel, mai durante un dialogo o una
battuta). Ogni scena ha la sua posizione in `map`; un posto nuovo entra con una riga. Test: posti
solo visti, strade, viaggio rifiutato in un dialogo; nel browser dal Trebbio alla Piazza.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UdeKd62opy9PKgpQXtVctF
This commit is contained in:
2026-10-23 15:59:29 +02:00
co-authored by Claude Opus 5.5
parent e743315f0f
commit ce4da39c8d
8 changed files with 123 additions and 1 deletions
+29
View File
@@ -78,6 +78,31 @@ $('credits-list').replaceChildren(...(story.credits ?? []).flatMap(({ role, name
for (const b of document.querySelectorAll('.open-credits')) b.addEventListener('click', () => { $('credits').hidden = false; });
$('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).
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;
}));
$('map').hidden = false;
}
$('map-button').addEventListener('click', openMap);
$('close-map').addEventListener('click', () => { $('map').hidden = true; });
function showTitle() {
running = false;
const saved = storage && readSave(storage);
@@ -170,6 +195,8 @@ function updateChoices() {
window.addEventListener('keydown', e => {
if (e.target === $('volume')) return;
if (!$('credits').hidden) { if (e.key === 'Escape') $('credits').hidden = true; return; }
if (!$('map').hidden) { if (e.key === 'Escape' || e.key === 'p' || e.key === 'P') $('map').hidden = true; return; }
if ((e.key === 'p' || e.key === 'P') && running) { openMap(); return; }
if (!$('intro').hidden && [' ', 'Enter'].includes(e.key)) { e.preventDefault(); nextIntro(); return; }
if (e.key === 'm' || e.key === 'M') { music.toggle(); saveAudio(); showSound(); return; }
if (!running) return;
@@ -204,6 +231,8 @@ function updateUi() {
updateInventory();
updateChoices();
updateSpeech();
// Il pulsante della mappa c'è solo in partita, fuori dai dialoghi, e quando c'è almeno un altro posto dove andare.
$('map-button').hidden = !running || !!game.dialogue || game.mapPlaces().length < 2;
if (game.state.ended && !game.speech && !game.queue.length) {
running = false;
$('ending').hidden = false;