Prototipo del motore: scena, camminata, verbi, inventario, dialoghi, salvataggio

Motore guidato dai dati con due scene di prova (Piazza e salita alla Fortezza),
percorsi su area concava, clic intelligente e pressione lunga, test della soluzione
completa in node e nel browser con Playwright. Nel documento la leggenda del nonno.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-23 00:08:00 +02:00
co-authored by Claude Opus 5.5
parent 0c5cd240e4
commit 826f5f99ec
22 changed files with 1572 additions and 1 deletions
+70
View File
@@ -0,0 +1,70 @@
:root {
--bg: #1b1420;
--panel: #2a2030;
--ink: #f4efe4;
--dim: #b9a9c2;
--accent: #ffd27a;
--blue: #6fa8ff;
--font: "Trebuchet MS", "Segoe UI", system-ui, sans-serif;
}
* { box-sizing: border-box; }
[hidden] { display: none !important; }
html, body { margin: 0; height: 100%; background: var(--bg); color: var(--ink); font-family: var(--font); }
body { display: flex; justify-content: center; overflow-x: hidden; -webkit-tap-highlight-color: transparent; }
#app { width: min(100vw, 1280px, calc((100dvh - 250px) * 16 / 9)); min-width: min(100vw, 320px); display: flex; flex-direction: column; padding: env(safe-area-inset-top) 0 env(safe-area-inset-bottom); }
#stage { position: relative; width: 100%; aspect-ratio: 16 / 9; background: #000; user-select: none; touch-action: manipulation; }
#scene { width: 100%; height: 100%; display: block; image-rendering: pixelated; cursor: crosshair; }
#speech { position: absolute; left: 0; top: 0; max-width: 46%; transform: translate(-50%, -100%); pointer-events: none;
font-size: clamp(14px, 2.3vw, 26px); font-weight: bold; line-height: 1.2; text-align: center;
text-shadow: 2px 0 #000, -2px 0 #000, 0 2px #000, 0 -2px #000, 2px 2px #000, -2px -2px #000; }
#speech:empty { display: none; }
#sentence { min-height: 1.8em; padding: .25em .6em; text-align: center; color: var(--blue); font-size: clamp(15px, 2vw, 22px); font-weight: bold; background: var(--panel); }
#panel { display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr); gap: 8px; padding: 8px; background: var(--panel); }
#verbs { display: grid; grid-template-columns: repeat(3, 1fr); gap: 4px; }
#verbs button, #inventory button { font: inherit; color: var(--dim); background: #3a2d42; border: 2px solid #4b3a55; border-radius: 4px;
padding: .35em .2em; font-size: clamp(13px, 1.7vw, 19px); font-weight: bold; cursor: pointer; }
#verbs button:hover, #inventory button:hover { color: var(--ink); }
#verbs button[aria-pressed="true"] { color: var(--bg); background: var(--accent); border-color: var(--accent); }
#inventory { display: grid; grid-template-columns: repeat(3, 1fr); grid-auto-rows: minmax(2.4em, auto); gap: 4px; align-content: start; }
#inventory button { display: flex; align-items: center; gap: .35em; justify-content: center; color: var(--ink); }
#inventory button[aria-pressed="true"] { border-color: var(--accent); }
#inventory i { width: .8em; height: .8em; border-radius: 50% 50% 50% 0; flex: none; }
#choices { margin: 0; padding: 10px 14px 12px 2.4em; background: var(--panel); min-height: 9.5em; }
#choices li { padding: .25em 0; font-size: clamp(15px, 2vw, 22px); font-weight: bold; color: var(--dim); cursor: pointer; }
#choices li:hover, #choices li:focus { color: var(--accent); outline: none; }
.overlay { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: .6em;
padding: 16px; text-align: center; background: radial-gradient(circle at 50% 35%, rgba(60, 40, 70, .82), rgba(15, 10, 20, .96)); }
.overlay[hidden] { display: none; }
.overlay h1 { margin: 0; font-size: clamp(30px, 7vw, 76px); line-height: 1; letter-spacing: .02em; color: var(--ink); text-shadow: 3px 3px 0 #000; }
.overlay h1 span { color: #7fe08a; }
.overlay h2 { margin: 0; font-size: clamp(24px, 5vw, 52px); color: var(--accent); }
.overlay p { margin: 0; max-width: 34em; font-size: clamp(13px, 2vw, 20px); }
.subtitle { color: var(--dim); }
.dedication { margin-top: .8em !important; font-style: italic; color: var(--accent); }
.buttons { display: flex; gap: 10px; flex-wrap: wrap; justify-content: center; margin-top: .4em; }
.buttons button { font: inherit; font-weight: bold; font-size: clamp(15px, 2.2vw, 22px); padding: .45em 1.2em; border-radius: 6px; cursor: pointer;
color: var(--bg); background: var(--accent); border: 0; }
#continue { background: #7fe08a; }
#rotate { display: none; padding: 1em; text-align: center; color: var(--dim); }
@media (orientation: portrait) and (max-width: 700px) { #rotate { display: block; } }
/* Telefono in orizzontale: la scena prende tutta l'altezza, verbi e inventario vanno di lato. */
@media (orientation: landscape) and (max-height: 520px) {
#app { width: 100vw; flex-direction: row; }
#stage { flex: none; width: min(calc(100dvh * 16 / 9), 68vw); align-self: flex-start; }
#side { flex: 1; min-width: 0; display: flex; flex-direction: column; background: var(--panel); }
#sentence { font-size: 14px; }
#panel { grid-template-columns: 1fr; gap: 6px; padding: 6px; }
#verbs, #inventory { grid-template-columns: repeat(2, 1fr); }
#verbs button, #inventory button, #choices li { font-size: 14px; }
#choices { min-height: 0; padding: 6px 8px 6px 2em; }
}
#error { position: fixed; inset: auto 16px 16px; padding: 12px; background: #7a1f1f; color: #fff; border-radius: 6px; }