Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
447c150974 | ||
|
|
95e7777dbc | ||
|
|
26697cd9c2 | ||
|
|
de303c5825 | ||
|
|
1fabb6e543 | ||
|
|
32a3d8a7c5 | ||
|
|
4bda52d9ac | ||
|
|
ec008b5ea1 | ||
|
|
73f3418bab | ||
|
|
ce4e47a2ed | ||
|
|
f6fd2fdfdc | ||
|
|
9d9dc81bcb | ||
|
|
bc19d6be53 | ||
|
|
c54023083a | ||
|
|
af6861350d |
@@ -12,6 +12,7 @@ COPY assets/fonts /usr/share/nginx/html/assets/fonts
|
|||||||
COPY assets/voices /usr/share/nginx/html/assets/voices
|
COPY assets/voices /usr/share/nginx/html/assets/voices
|
||||||
COPY assets/credits /usr/share/nginx/html/assets/credits
|
COPY assets/credits /usr/share/nginx/html/assets/credits
|
||||||
COPY assets/effects /usr/share/nginx/html/assets/effects
|
COPY assets/effects /usr/share/nginx/html/assets/effects
|
||||||
|
COPY assets/closeups /usr/share/nginx/html/assets/closeups
|
||||||
|
|
||||||
# Le immagini e i font citati da index.html e style.css prendono ?v=<versione>, come quelli caricati dal codice.
|
# Le immagini e i font citati da index.html e style.css prendono ?v=<versione>, come quelli caricati dal codice.
|
||||||
RUN cd /usr/share/nginx/html \
|
RUN cd /usr/share/nginx/html \
|
||||||
|
|||||||
@@ -41,6 +41,12 @@ python3 -m http.server 8000 # poi http://localhost:8000
|
|||||||
Clic = azione più sensata (parla, guarda, vai); clic destro o pressione lunga = guarda; un verbo scelto vale per il
|
Clic = azione più sensata (parla, guarda, vai); clic destro o pressione lunga = guarda; un verbo scelto vale per il
|
||||||
clic successivo. Spazio salta la battuta, i numeri scelgono nel dialogo, Esc annulla il verbo.
|
clic successivo. Spazio salta la battuta, i numeri scelgono nel dialogo, Esc annulla il verbo.
|
||||||
|
|
||||||
|
Il libro dell'oratorio si apre e si sfoglia con clic o tocco; Esc lo chiude. Nella fessura della Fortezza,
|
||||||
|
la torcia segue mouse o dito (anche trascinando): si cercano i dettagli tenendo brevemente la luce su di essi.
|
||||||
|
Si possono usare anche le frecce, oppure Invio per cercare il prossimo dettaglio. «Torna fuori» permette di
|
||||||
|
riprovare; dopo il ritrovamento, «Continua» conclude il capitolo.
|
||||||
|
Il volume dei suoni ambientali e del fruscio delle pagine si regola in **Pausa → Ambiente ed effetti**.
|
||||||
|
|
||||||
## In Docker
|
## In Docker
|
||||||
|
|
||||||
```zsh
|
```zsh
|
||||||
@@ -64,5 +70,6 @@ make down
|
|||||||
npm test # logica, storia coerente, soluzione percorsa dall'inizio alla fine
|
npm test # logica, storia coerente, soluzione percorsa dall'inizio alla fine
|
||||||
npm install && npx playwright install chromium-headless-shell
|
npm install && npx playwright install chromium-headless-shell
|
||||||
npm run browser # partita completa con clic veri in Chromium, salvataggio, telefono
|
npm run browser # partita completa con clic veri in Chromium, salvataggio, telefono
|
||||||
|
npm run browser -- --media-only # libro, torcia e audio: controllo mirato desktop/telefono
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -5,65 +5,65 @@
|
|||||||
"sit": {
|
"sit": {
|
||||||
"x": 0,
|
"x": 0,
|
||||||
"y": 0,
|
"y": 0,
|
||||||
"w": 76,
|
"w": 77,
|
||||||
"h": 96,
|
"h": 96,
|
||||||
"ax": 31.4,
|
"ax": 32.9,
|
||||||
"ay": 96
|
"ay": 96
|
||||||
},
|
},
|
||||||
"doze": {
|
"doze": {
|
||||||
"x": 78,
|
"x": 79,
|
||||||
"y": 0,
|
"y": 0,
|
||||||
"w": 76,
|
"w": 77,
|
||||||
"h": 96,
|
"h": 96,
|
||||||
"ax": 31.5,
|
"ax": 33.0,
|
||||||
"ay": 96
|
"ay": 96
|
||||||
},
|
},
|
||||||
"talk": {
|
"talk": {
|
||||||
"x": 156,
|
"x": 158,
|
||||||
"y": 0,
|
"y": 0,
|
||||||
"w": 67,
|
"w": 68,
|
||||||
"h": 96,
|
"h": 96,
|
||||||
"ax": 25.1,
|
"ax": 26.3,
|
||||||
"ay": 96
|
"ay": 96
|
||||||
},
|
},
|
||||||
"explain": {
|
"explain": {
|
||||||
"x": 225,
|
"x": 228,
|
||||||
"y": 0,
|
"y": 0,
|
||||||
"w": 62,
|
"w": 68,
|
||||||
"h": 96,
|
"h": 96,
|
||||||
"ax": 27.4,
|
"ax": 29.9,
|
||||||
"ay": 96
|
"ay": 96
|
||||||
},
|
},
|
||||||
"point": {
|
"point": {
|
||||||
"x": 289,
|
"x": 298,
|
||||||
"y": 0,
|
"y": 0,
|
||||||
"w": 74,
|
"w": 78,
|
||||||
"h": 97,
|
"h": 97,
|
||||||
"ax": 31.5,
|
"ax": 33.3,
|
||||||
"ay": 97
|
"ay": 97
|
||||||
},
|
},
|
||||||
"laugh": {
|
"laugh": {
|
||||||
"x": 365,
|
"x": 378,
|
||||||
"y": 0,
|
"y": 0,
|
||||||
"w": 70,
|
"w": 71,
|
||||||
"h": 97,
|
"h": 97,
|
||||||
"ax": 23.2,
|
"ax": 22.8,
|
||||||
"ay": 97
|
"ay": 97
|
||||||
},
|
},
|
||||||
"cat": {
|
"cat": {
|
||||||
"x": 437,
|
"x": 451,
|
||||||
"y": 0,
|
"y": 0,
|
||||||
"w": 67,
|
"w": 68,
|
||||||
"h": 95,
|
"h": 96,
|
||||||
"ax": 24.1,
|
"ax": 26.1,
|
||||||
"ay": 95
|
"ay": 96
|
||||||
},
|
},
|
||||||
"shrug": {
|
"shrug": {
|
||||||
"x": 506,
|
"x": 521,
|
||||||
"y": 0,
|
"y": 0,
|
||||||
"w": 81,
|
"w": 83,
|
||||||
"h": 97,
|
"h": 97,
|
||||||
"ax": 38.9,
|
"ax": 40.2,
|
||||||
"ay": 97
|
"ay": 97
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 95 KiB After Width: | Height: | Size: 94 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 143 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 139 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 56 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+314
-70
@@ -91,6 +91,22 @@
|
|||||||
"file": "andrea-af4d717814.mp3",
|
"file": "andrea-af4d717814.mp3",
|
||||||
"sec": 6.44
|
"sec": 6.44
|
||||||
},
|
},
|
||||||
|
"vecchietto|Dice che Andrea ha trovato un serpente lungo dodici metri.": {
|
||||||
|
"file": "vecchietto-cc1d61420b.mp3",
|
||||||
|
"sec": 3.64
|
||||||
|
},
|
||||||
|
"vecchietta|Ma quale serpente. Secondo me va in Fortezza solo per farsi le canne: torna sempre con gli occhi rossi!": {
|
||||||
|
"file": "vecchietta-c11979f5e8.mp3",
|
||||||
|
"sec": 6.73
|
||||||
|
},
|
||||||
|
"andrea|Sono qui, eh. Vi sento.": {
|
||||||
|
"file": "andrea-5debd43bf6.mp3",
|
||||||
|
"sec": 2.64
|
||||||
|
},
|
||||||
|
"vecchietta|Oh! Andrea! Si parlava d'un altro.": {
|
||||||
|
"file": "vecchietta-1cbc047e44.mp3",
|
||||||
|
"sec": 4.9
|
||||||
|
},
|
||||||
"andrea|Se li porto via, il paese resta senza notizie.": {
|
"andrea|Se li porto via, il paese resta senza notizie.": {
|
||||||
"file": "andrea-566475abe2.mp3",
|
"file": "andrea-566475abe2.mp3",
|
||||||
"sec": 3.48
|
"sec": 3.48
|
||||||
@@ -111,6 +127,26 @@
|
|||||||
"file": "andrea-eeb5a2273c.mp3",
|
"file": "andrea-eeb5a2273c.mp3",
|
||||||
"sec": 1.3
|
"sec": 1.3
|
||||||
},
|
},
|
||||||
|
"vecchietta|Al limone! Da ragazza me ne mangiavo tre di fila.": {
|
||||||
|
"file": "vecchietta-15dbd36313.mp3",
|
||||||
|
"sec": 3.24
|
||||||
|
},
|
||||||
|
"vecchietto|E poi tre giorni a letto.": {
|
||||||
|
"file": "vecchietto-6a0dcb4430.mp3",
|
||||||
|
"sec": 1.37
|
||||||
|
},
|
||||||
|
"andrea|Me lo tengo io, allora.": {
|
||||||
|
"file": "andrea-d5aeb501d8.mp3",
|
||||||
|
"sec": 1.16
|
||||||
|
},
|
||||||
|
"vecchietto|«La storia infinita»? Alla mia età, figliolo, meglio qualcosa di corto.": {
|
||||||
|
"file": "vecchietto-27843b8226.mp3",
|
||||||
|
"sec": 5.02
|
||||||
|
},
|
||||||
|
"andrea|Fidati: è più corto di quel che sembra.": {
|
||||||
|
"file": "andrea-20c5ab3680.mp3",
|
||||||
|
"sec": 2.41
|
||||||
|
},
|
||||||
"andrea|Qualcosa luccica, proprio sotto i piedi dei vecchietti.": {
|
"andrea|Qualcosa luccica, proprio sotto i piedi dei vecchietti.": {
|
||||||
"file": "andrea-9a8732a3aa.mp3",
|
"file": "andrea-9a8732a3aa.mp3",
|
||||||
"sec": 3.97
|
"sec": 3.97
|
||||||
@@ -175,6 +211,10 @@
|
|||||||
"file": "andrea-fd10e3f083.mp3",
|
"file": "andrea-fd10e3f083.mp3",
|
||||||
"sec": 3.04
|
"sec": 3.04
|
||||||
},
|
},
|
||||||
|
"andrea|Di giorno la torcia non serve: le impronte si vedono benissimo. È il buio della fessura, il problema.": {
|
||||||
|
"file": "andrea-36648fc8d5.mp3",
|
||||||
|
"sec": 7.66
|
||||||
|
},
|
||||||
"andrea|Ormai lo so: è passato di qui. E le impronte piegano verso il bastione.": {
|
"andrea|Ormai lo so: è passato di qui. E le impronte piegano verso il bastione.": {
|
||||||
"file": "andrea-5b0cf4f9cf.mp3",
|
"file": "andrea-5b0cf4f9cf.mp3",
|
||||||
"sec": 5.03
|
"sec": 5.03
|
||||||
@@ -231,38 +271,14 @@
|
|||||||
"file": "andrea-aa9b313a43.mp3",
|
"file": "andrea-aa9b313a43.mp3",
|
||||||
"sec": 2.22
|
"sec": 2.22
|
||||||
},
|
},
|
||||||
|
"andrea|Troppo buio: non vedo nemmeno dove lo infilo. Prima ci vuole una luce.": {
|
||||||
|
"file": "andrea-59df1ada58.mp3",
|
||||||
|
"sec": 4.78
|
||||||
|
},
|
||||||
"andrea|Accendo la torcia e la punto dentro...": {
|
"andrea|Accendo la torcia e la punto dentro...": {
|
||||||
"file": "andrea-68a845881b.mp3",
|
"file": "andrea-68a845881b.mp3",
|
||||||
"sec": 1.94
|
"sec": 1.94
|
||||||
},
|
},
|
||||||
"andrea|Laggiù, appoggiato al muro, c'è un angolo di tela dipinta: una strada bianca, e un omino con la maglia rossa e le braccia alzate.": {
|
|
||||||
"file": "andrea-6484641c58.mp3",
|
|
||||||
"sec": 8.67
|
|
||||||
},
|
|
||||||
"andrea|È il palio! Il quadro dei ragazzi delle medie!": {
|
|
||||||
"file": "andrea-51ec04c16e.mp3",
|
|
||||||
"sec": 3.54
|
|
||||||
},
|
|
||||||
"andrea|E quelli... sono due occhi gialli!": {
|
|
||||||
"file": "andrea-0f5f2a4b2f.mp3",
|
|
||||||
"sec": 2.63
|
|
||||||
},
|
|
||||||
"andrea|Spariti nel buio.": {
|
|
||||||
"file": "andrea-f34cc00733.mp3",
|
|
||||||
"sec": 1.17
|
|
||||||
},
|
|
||||||
"andrea|Il Regolo. E ha il nostro palio.": {
|
|
||||||
"file": "andrea-1b2601be96.mp3",
|
|
||||||
"sec": 2.77
|
|
||||||
},
|
|
||||||
"andrea|Però non l'ha portato via: l'ha messo proprio lassù, in Fortezza. Dove domani portiamo i mattoni col passamano.": {
|
|
||||||
"file": "andrea-abeac78e68.mp3",
|
|
||||||
"sec": 7.13
|
|
||||||
},
|
|
||||||
"andrea|Il palio è già pronto ad aspettarci. Torno giù a dirlo a tutti: la festa si fa!": {
|
|
||||||
"file": "andrea-28f672ef5f.mp3",
|
|
||||||
"sec": 5.42
|
|
||||||
},
|
|
||||||
"andrea|La Pieve di San Pietro. Il mio rione: noi bianchi.": {
|
"andrea|La Pieve di San Pietro. Il mio rione: noi bianchi.": {
|
||||||
"file": "andrea-43fd5c2b27.mp3",
|
"file": "andrea-43fd5c2b27.mp3",
|
||||||
"sec": 4.46
|
"sec": 4.46
|
||||||
@@ -279,6 +295,14 @@
|
|||||||
"file": "andrea-6012288000.mp3",
|
"file": "andrea-6012288000.mp3",
|
||||||
"sec": 7.97
|
"sec": 7.97
|
||||||
},
|
},
|
||||||
|
"san_pietro|Figliolo, io tengo le chiavi, non le squame. Portala a chi l'ha persa.": {
|
||||||
|
"file": "san_pietro-28fac8029b.mp3",
|
||||||
|
"sec": 5.6
|
||||||
|
},
|
||||||
|
"san_pietro|Te l'ho data io: usala, non restituirla. Le chiavi servono alle porte.": {
|
||||||
|
"file": "san_pietro-72373bd589.mp3",
|
||||||
|
"sec": 6.13
|
||||||
|
},
|
||||||
"andrea|La statua di San Pietro, con le chiavi in mano. Lui il palio l'ha visto passare di sicuro.": {
|
"andrea|La statua di San Pietro, con le chiavi in mano. Lui il palio l'ha visto passare di sicuro.": {
|
||||||
"file": "andrea-0663f64ddf.mp3",
|
"file": "andrea-0663f64ddf.mp3",
|
||||||
"sec": 5.97
|
"sec": 5.97
|
||||||
@@ -427,13 +451,17 @@
|
|||||||
"file": "andrea-42e270af3d.mp3",
|
"file": "andrea-42e270af3d.mp3",
|
||||||
"sec": 6.21
|
"sec": 6.21
|
||||||
},
|
},
|
||||||
"andrea|Me lo prendo. Se è suo, il proprietario lo ritrova... prima o poi.": {
|
"andrea|Ricordo di aver visto il film da piccolo... era stupendo!": {
|
||||||
"file": "andrea-78a0a84b84.mp3",
|
"file": "andrea-5528e4c7b0.mp3",
|
||||||
"sec": 5.95
|
"sec": 4.06
|
||||||
},
|
},
|
||||||
"andrea|Il cancello di dietro.": {
|
"andrea|Il cancello di dietro. Se chiudo gli occhi vedo ancora l'A. Bettini, il campo da calcio di quando eravamo piccoli: lassù ci sono ancora i riflettori.": {
|
||||||
"file": "andrea-a2f0124f4d.mp3",
|
"file": "andrea-bc60e0ce13.mp3",
|
||||||
"sec": 1.41
|
"sec": 9.9
|
||||||
|
},
|
||||||
|
"andrea|Il primo vero campo del paese: inaugurato nel 1964 e intitolato ad Alberto Bettini, un giovane consigliere della società scomparso troppo presto.": {
|
||||||
|
"file": "andrea-f035c38acc.mp3",
|
||||||
|
"sec": 11.19
|
||||||
},
|
},
|
||||||
"andrea|Chiuso. Si apre solo quando c'è la festa.": {
|
"andrea|Chiuso. Si apre solo quando c'è la festa.": {
|
||||||
"file": "andrea-5e1cd26d46.mp3",
|
"file": "andrea-5e1cd26d46.mp3",
|
||||||
@@ -583,6 +611,10 @@
|
|||||||
"file": "andrea-a8dfddbe65.mp3",
|
"file": "andrea-a8dfddbe65.mp3",
|
||||||
"sec": 3.45
|
"sec": 3.45
|
||||||
},
|
},
|
||||||
|
"andrea|Un lucchetto non si pesca. Ci vuole la sua chiave.": {
|
||||||
|
"file": "andrea-d193b44288.mp3",
|
||||||
|
"sec": 3.65
|
||||||
|
},
|
||||||
"andrea|Il tabernacolo prima del ponte. Chi passa per andare via dal paese, un saluto glielo fa sempre.": {
|
"andrea|Il tabernacolo prima del ponte. Chi passa per andare via dal paese, un saluto glielo fa sempre.": {
|
||||||
"file": "andrea-78a5ef65f0.mp3",
|
"file": "andrea-78a5ef65f0.mp3",
|
||||||
"sec": 7.84
|
"sec": 7.84
|
||||||
@@ -623,13 +655,25 @@
|
|||||||
"file": "andrea-e47b3cebb5.mp3",
|
"file": "andrea-e47b3cebb5.mp3",
|
||||||
"sec": 4.87
|
"sec": 4.87
|
||||||
},
|
},
|
||||||
|
"barondeduke|Me la giochi? Ho un sette e un due, ma un sacco di fiducia.": {
|
||||||
|
"file": "barondeduke-52184c7c05.mp3",
|
||||||
|
"sec": 5.58
|
||||||
|
},
|
||||||
|
"andrea|No, Barone. A poker le squame non valgono.": {
|
||||||
|
"file": "andrea-40651c0ea4.mp3",
|
||||||
|
"sec": 4.39
|
||||||
|
},
|
||||||
|
"barondeduke|A questo giro non punto niente. Nemmeno un ghiacciolo.": {
|
||||||
|
"file": "barondeduke-eff8685095.mp3",
|
||||||
|
"sec": 4.28
|
||||||
|
},
|
||||||
"andrea|Il BaronDeDuke, col cappello da cowboy. Ha l'aria di uno che aspetta qualcuno, e che spera non lo veda nessuno.": {
|
"andrea|Il BaronDeDuke, col cappello da cowboy. Ha l'aria di uno che aspetta qualcuno, e che spera non lo veda nessuno.": {
|
||||||
"file": "andrea-0bd1b0f32e.mp3",
|
"file": "andrea-0bd1b0f32e.mp3",
|
||||||
"sec": 8.7
|
"sec": 8.7
|
||||||
},
|
},
|
||||||
"andrea|Baron! Che ci fai qui?": {
|
"andrea|Barone! Che ci fai qui?": {
|
||||||
"file": "andrea-1b59141c98.mp3",
|
"file": "andrea-83abae1419.mp3",
|
||||||
"sec": 2.59
|
"sec": 2.91
|
||||||
},
|
},
|
||||||
"barondeduke|Aspetto uno che mi deve riportare le mutande.": {
|
"barondeduke|Aspetto uno che mi deve riportare le mutande.": {
|
||||||
"file": "barondeduke-3ea60b7083.mp3",
|
"file": "barondeduke-3ea60b7083.mp3",
|
||||||
@@ -643,9 +687,9 @@
|
|||||||
"file": "barondeduke-5542a06624.mp3",
|
"file": "barondeduke-5542a06624.mp3",
|
||||||
"sec": 1.65
|
"sec": 1.65
|
||||||
},
|
},
|
||||||
"barondeduke|In mano avevo full. E ho detto: «Male male si divide».": {
|
"barondeduke|Avevo due donne e due jack. Entra la terza donna, e penso: «Male male si divide».": {
|
||||||
"file": "barondeduke-944c3e57dc.mp3",
|
"file": "barondeduke-d4ff967179.mp3",
|
||||||
"sec": 5.03
|
"sec": 7.64
|
||||||
},
|
},
|
||||||
"andrea|E invece?": {
|
"andrea|E invece?": {
|
||||||
"file": "andrea-435306c242.mp3",
|
"file": "andrea-435306c242.mp3",
|
||||||
@@ -799,18 +843,22 @@
|
|||||||
"file": "andrea-bb70dea2a6.mp3",
|
"file": "andrea-bb70dea2a6.mp3",
|
||||||
"sec": 2.15
|
"sec": 2.15
|
||||||
},
|
},
|
||||||
|
"arcu|Che è, la mancia? Una squama? Grazie, la metto in cassaforte.": {
|
||||||
|
"file": "arcu-8c7f1850a3.mp3",
|
||||||
|
"sec": 5.84
|
||||||
|
},
|
||||||
|
"arcu|Tienila te, che io di roba verde ne ho già abbastanza sul lavoro.": {
|
||||||
|
"file": "arcu-bb69d88654.mp3",
|
||||||
|
"sec": 3.23
|
||||||
|
},
|
||||||
|
"arcu|Un libro? A me? Lo sai che io leggo solo le etichette degli armadi.": {
|
||||||
|
"file": "arcu-1da81f6f98.mp3",
|
||||||
|
"sec": 6.44
|
||||||
|
},
|
||||||
"andrea|L'Arcu, il mio amico di sempre. Davanti al circolino, come se ci fosse nato.": {
|
"andrea|L'Arcu, il mio amico di sempre. Davanti al circolino, come se ci fosse nato.": {
|
||||||
"file": "andrea-8ddab2d024.mp3",
|
"file": "andrea-8ddab2d024.mp3",
|
||||||
"sec": 5.79
|
"sec": 5.79
|
||||||
},
|
},
|
||||||
"andrea|Arcu! Ma che è sempre là, Borgo?": {
|
|
||||||
"file": "andrea-aaeb40d873.mp3",
|
|
||||||
"sec": 3.42
|
|
||||||
},
|
|
||||||
"arcu|E chi lo sposta???": {
|
|
||||||
"file": "arcu-64735a5925.mp3",
|
|
||||||
"sec": 0.97
|
|
||||||
},
|
|
||||||
"andrea|Il ponte vecchio, coi suoi due archi. Chissà quante piene ha visto passare: io al primo temporale cerco riparo.": {
|
"andrea|Il ponte vecchio, coi suoi due archi. Chissà quante piene ha visto passare: io al primo temporale cerco riparo.": {
|
||||||
"file": "andrea-01ec1d03ec.mp3",
|
"file": "andrea-01ec1d03ec.mp3",
|
||||||
"sec": 7.67
|
"sec": 7.67
|
||||||
@@ -843,6 +891,18 @@
|
|||||||
"file": "andrea-455ac4031a.mp3",
|
"file": "andrea-455ac4031a.mp3",
|
||||||
"sec": 4.96
|
"sec": 4.96
|
||||||
},
|
},
|
||||||
|
"andrea|Tosca, guarda cosa ho trovato.": {
|
||||||
|
"file": "andrea-f5ff3c0ef9.mp3",
|
||||||
|
"sec": 2.27
|
||||||
|
},
|
||||||
|
"tosca|Bella. Ma nella cedrata questa non ce la metto.": {
|
||||||
|
"file": "tosca-7451ea2ef5.mp3",
|
||||||
|
"sec": 3.81
|
||||||
|
},
|
||||||
|
"tosca|Un libro? Andrea, qui si legge solo il listino. E costa meno.": {
|
||||||
|
"file": "tosca-ffc7cea9af.mp3",
|
||||||
|
"sec": 6.46
|
||||||
|
},
|
||||||
"andrea|Il chiosco del tennis. D'estate qui c'è la Tosca coi ghiaccioli.": {
|
"andrea|Il chiosco del tennis. D'estate qui c'è la Tosca coi ghiaccioli.": {
|
||||||
"file": "andrea-24214bad4e.mp3",
|
"file": "andrea-24214bad4e.mp3",
|
||||||
"sec": 5.6
|
"sec": 5.6
|
||||||
@@ -963,6 +1023,26 @@
|
|||||||
"file": "andrea-468fe91000.mp3",
|
"file": "andrea-468fe91000.mp3",
|
||||||
"sec": 3.28
|
"sec": 3.28
|
||||||
},
|
},
|
||||||
|
"leone|Ehi! Mi abbagli! Sono di terracotta, mica cieco.": {
|
||||||
|
"file": "leone-4addbac9c7.mp3",
|
||||||
|
"sec": 6
|
||||||
|
},
|
||||||
|
"andrea|Scusa, leone.": {
|
||||||
|
"file": "andrea-66a622cd5e.mp3",
|
||||||
|
"sec": 0.92
|
||||||
|
},
|
||||||
|
"leone|Quella tienila per il buio. Qui c'è il sole, se non l'hai notato.": {
|
||||||
|
"file": "leone-19d904d4e1.mp3",
|
||||||
|
"sec": 5.66
|
||||||
|
},
|
||||||
|
"leone|Una squama? Io di squame ne ho viste... mai. Io faccio la guardia alla salita.": {
|
||||||
|
"file": "leone-7bd7f55e53.mp3",
|
||||||
|
"sec": 8.73
|
||||||
|
},
|
||||||
|
"andrea|Lo so, lo so. Alla salita.": {
|
||||||
|
"file": "andrea-62c970e189.mp3",
|
||||||
|
"sec": 2.65
|
||||||
|
},
|
||||||
"andrea|Di là si va alla scuola. Ci ho passato abbastanza anni, grazie.": {
|
"andrea|Di là si va alla scuola. Ci ho passato abbastanza anni, grazie.": {
|
||||||
"file": "andrea-f6fa5d6d6d.mp3",
|
"file": "andrea-f6fa5d6d6d.mp3",
|
||||||
"sec": 4.03
|
"sec": 4.03
|
||||||
@@ -979,6 +1059,14 @@
|
|||||||
"file": "andrea-f5d55187e8.mp3",
|
"file": "andrea-f5d55187e8.mp3",
|
||||||
"sec": 5.11
|
"sec": 5.11
|
||||||
},
|
},
|
||||||
|
"tozzino|Grazie, ma prima della partita niente zuccheri. Federer non li tocca.": {
|
||||||
|
"file": "tozzino-cfc1b1fa67.mp3",
|
||||||
|
"sec": 4.8
|
||||||
|
},
|
||||||
|
"tozzino|Una torcia? Se Federer arriva di notte, magari. Per ora tienila te.": {
|
||||||
|
"file": "tozzino-18e6d6edff.mp3",
|
||||||
|
"sec": 5.58
|
||||||
|
},
|
||||||
"andrea|Il Tozzino, vestito di bianco da capo a piedi, con la racchetta. Guarda l'orologio ogni dieci secondi.": {
|
"andrea|Il Tozzino, vestito di bianco da capo a piedi, con la racchetta. Guarda l'orologio ogni dieci secondi.": {
|
||||||
"file": "andrea-3c32888a15.mp3",
|
"file": "andrea-3c32888a15.mp3",
|
||||||
"sec": 8.1
|
"sec": 8.1
|
||||||
@@ -988,20 +1076,20 @@
|
|||||||
"sec": 3.1
|
"sec": 3.1
|
||||||
},
|
},
|
||||||
"tozzino|Aspetto Federer. Oggi si fa una partita.": {
|
"tozzino|Aspetto Federer. Oggi si fa una partita.": {
|
||||||
"file": "tozzino-a069d2c5e2.mp3",
|
"file": "tozzino-c3898e9bdb.mp3",
|
||||||
"sec": 2.85
|
"sec": 3.23
|
||||||
},
|
},
|
||||||
"andrea|Federer? Roger Federer?": {
|
"andrea|Federer? Roger Federer?": {
|
||||||
"file": "andrea-70f150bdec.mp3",
|
"file": "andrea-70f150bdec.mp3",
|
||||||
"sec": 2.67
|
"sec": 2.67
|
||||||
},
|
},
|
||||||
"tozzino|E chi sennò? Ha chiamato ora: è imbottigliato in Bolognese.": {
|
"tozzino|E chi sennò? Ha chiamato ora: è imbottigliato in Bolognese.": {
|
||||||
"file": "tozzino-5072201408.mp3",
|
"file": "tozzino-d51159c364.mp3",
|
||||||
"sec": 4.3
|
"sec": 4.08
|
||||||
},
|
},
|
||||||
"tozzino|Se non arriva, la vinco a tavolino.": {
|
"tozzino|Se non arriva, la vinco a tavolino.": {
|
||||||
"file": "tozzino-c1736e2d62.mp3",
|
"file": "tozzino-c06cc01612.mp3",
|
||||||
"sec": 1.42
|
"sec": 2.06
|
||||||
},
|
},
|
||||||
"andrea|La Carza. A maggio c'è poca acqua: d'estate si scendeva a fare le dighe coi sassi.": {
|
"andrea|La Carza. A maggio c'è poca acqua: d'estate si scendeva a fare le dighe coi sassi.": {
|
||||||
"file": "andrea-91be1de49b.mp3",
|
"file": "andrea-91be1de49b.mp3",
|
||||||
@@ -1139,6 +1227,14 @@
|
|||||||
"file": "andrea-a1dab4073c.mp3",
|
"file": "andrea-a1dab4073c.mp3",
|
||||||
"sec": 3.82
|
"sec": 3.82
|
||||||
},
|
},
|
||||||
|
"castello|Luce? In seicento anni ne ho vista tanta. Tienila per il buio, che quello non manca mai.": {
|
||||||
|
"file": "castello-c2cc9224c5.mp3",
|
||||||
|
"sec": 9.1
|
||||||
|
},
|
||||||
|
"castello|Non a me. Portala vicino a chi l'ha persa: le cose parlano solo dove sono cadute.": {
|
||||||
|
"file": "castello-3267e20838.mp3",
|
||||||
|
"sec": 7.74
|
||||||
|
},
|
||||||
"andrea|La torre del Trebbio. Da ragazzo ci si rifugiò Amerigo Vespucci, per scappare dalla peste di Firenze.": {
|
"andrea|La torre del Trebbio. Da ragazzo ci si rifugiò Amerigo Vespucci, per scappare dalla peste di Firenze.": {
|
||||||
"file": "andrea-14cbceece4.mp3",
|
"file": "andrea-14cbceece4.mp3",
|
||||||
"sec": 6.99
|
"sec": 6.99
|
||||||
@@ -1183,22 +1279,6 @@
|
|||||||
"file": "andrea-23e40a2495.mp3",
|
"file": "andrea-23e40a2495.mp3",
|
||||||
"sec": 5.74
|
"sec": 5.74
|
||||||
},
|
},
|
||||||
"andrea|Vediamo da dove comincia...": {
|
|
||||||
"file": "andrea-239bf733a6.mp3",
|
|
||||||
"sec": 1.26
|
|
||||||
},
|
|
||||||
"andrea|C'è una pagina sola. Con scritto: «FINE».": {
|
|
||||||
"file": "andrea-1d80123a55.mp3",
|
|
||||||
"sec": 3.93
|
|
||||||
},
|
|
||||||
"andrea|Infinita, dicevano.": {
|
|
||||||
"file": "andrea-77f1348d3a.mp3",
|
|
||||||
"sec": 2.13
|
|
||||||
},
|
|
||||||
"andrea|Leggere adesso? Prima il palio. E poi, a quanto pare, si fa presto.": {
|
|
||||||
"file": "andrea-3a6af3897f.mp3",
|
|
||||||
"sec": 6.06
|
|
||||||
},
|
|
||||||
"andrea|Un ghiacciolo al limone. Si scioglie a guardarlo.": {
|
"andrea|Un ghiacciolo al limone. Si scioglie a guardarlo.": {
|
||||||
"file": "andrea-8c9713081a.mp3",
|
"file": "andrea-8c9713081a.mp3",
|
||||||
"sec": 3.44
|
"sec": 3.44
|
||||||
@@ -1315,6 +1395,10 @@
|
|||||||
"file": "andrea-2d0e3c759e.mp3",
|
"file": "andrea-2d0e3c759e.mp3",
|
||||||
"sec": 1.39
|
"sec": 1.39
|
||||||
},
|
},
|
||||||
|
"andrea|Tosca, cosa si dice in giro?": {
|
||||||
|
"file": "andrea-be96b05f57.mp3",
|
||||||
|
"sec": 2.04
|
||||||
|
},
|
||||||
"andrea|Niente, grazie Tosca.": {
|
"andrea|Niente, grazie Tosca.": {
|
||||||
"file": "andrea-2637918e77.mp3",
|
"file": "andrea-2637918e77.mp3",
|
||||||
"sec": 1.32
|
"sec": 1.32
|
||||||
@@ -1339,6 +1423,14 @@
|
|||||||
"file": "tosca-376fbb9f17.mp3",
|
"file": "tosca-376fbb9f17.mp3",
|
||||||
"sec": 2.41
|
"sec": 2.41
|
||||||
},
|
},
|
||||||
|
"tosca|Che sei andato sotto la Fortezza da solo. Il paese parla, Andrea.": {
|
||||||
|
"file": "tosca-ad26d2c8dc.mp3",
|
||||||
|
"sec": 5.16
|
||||||
|
},
|
||||||
|
"tosca|Prenditi una cedrata, che le chiacchiere mettono sete.": {
|
||||||
|
"file": "tosca-940ffeb62c.mp3",
|
||||||
|
"sec": 2.98
|
||||||
|
},
|
||||||
"tosca|Quando ti viene sete, sai dove trovarmi.": {
|
"tosca|Quando ti viene sete, sai dove trovarmi.": {
|
||||||
"file": "tosca-db2da31cef.mp3",
|
"file": "tosca-db2da31cef.mp3",
|
||||||
"sec": 2.31
|
"sec": 2.31
|
||||||
@@ -1403,6 +1495,18 @@
|
|||||||
"file": "andrea-379131645c.mp3",
|
"file": "andrea-379131645c.mp3",
|
||||||
"sec": 1.98
|
"sec": 1.98
|
||||||
},
|
},
|
||||||
|
"andrea|Ho trovato una squama, sotto la panchina.": {
|
||||||
|
"file": "andrea-5a36e0de20.mp3",
|
||||||
|
"sec": 2.57
|
||||||
|
},
|
||||||
|
"andrea|Sotto la Fortezza ci sono impronte, e vanno verso il bastione.": {
|
||||||
|
"file": "andrea-dc9addb491.mp3",
|
||||||
|
"sec": 3.56
|
||||||
|
},
|
||||||
|
"andrea|Ho una torcia. Stasera salgo alla Fortezza.": {
|
||||||
|
"file": "andrea-c458e32a56.mp3",
|
||||||
|
"sec": 4.28
|
||||||
|
},
|
||||||
"andrea|Ci vediamo dopo.": {
|
"andrea|Ci vediamo dopo.": {
|
||||||
"file": "andrea-7e9841c23a.mp3",
|
"file": "andrea-7e9841c23a.mp3",
|
||||||
"sec": 0.95
|
"sec": 0.95
|
||||||
@@ -1443,6 +1547,42 @@
|
|||||||
"file": "vecchietta-fe3c07afa2.mp3",
|
"file": "vecchietta-fe3c07afa2.mp3",
|
||||||
"sec": 5.11
|
"sec": 5.11
|
||||||
},
|
},
|
||||||
|
"vecchietta|L'avevo detto io, che luccicava!": {
|
||||||
|
"file": "vecchietta-8bcd369812.mp3",
|
||||||
|
"sec": 2.3
|
||||||
|
},
|
||||||
|
"vecchietto|Una squama a maggio? Allora il Regolo fa la muta, come le bisce.": {
|
||||||
|
"file": "vecchietto-33b2aadc49.mp3",
|
||||||
|
"sec": 4.64
|
||||||
|
},
|
||||||
|
"vecchietta|O l'ha persa uno della sfilata, col costume. Che ne sai.": {
|
||||||
|
"file": "vecchietta-51d10531a0.mp3",
|
||||||
|
"sec": 4.34
|
||||||
|
},
|
||||||
|
"vecchietto|Lo sapevo. Stanotte ho sentito raspare, dalla parte della Fortezza.": {
|
||||||
|
"file": "vecchietto-7204d5b851.mp3",
|
||||||
|
"sec": 5.29
|
||||||
|
},
|
||||||
|
"vecchietta|Tu stanotte dormivi. L'hai detto tu.": {
|
||||||
|
"file": "vecchietta-8f618fae8c.mp3",
|
||||||
|
"sec": 2.75
|
||||||
|
},
|
||||||
|
"vecchietto|Si può dormire e sentire. Alla mia età si fa tutto insieme.": {
|
||||||
|
"file": "vecchietto-320caa6792.mp3",
|
||||||
|
"sec": 4.92
|
||||||
|
},
|
||||||
|
"vecchietto|Di sera? Lassù? Allora salutaci il Regolo.": {
|
||||||
|
"file": "vecchietto-9d2e14790f.mp3",
|
||||||
|
"sec": 4.08
|
||||||
|
},
|
||||||
|
"vecchietta|E se ti mangia, almeno la festa ha un argomento.": {
|
||||||
|
"file": "vecchietta-7baa7686cd.mp3",
|
||||||
|
"sec": 2.94
|
||||||
|
},
|
||||||
|
"andrea|Grazie dell'incoraggiamento.": {
|
||||||
|
"file": "andrea-f845779a10.mp3",
|
||||||
|
"sec": 1.57
|
||||||
|
},
|
||||||
"vecchietta|Salutaci i tuoi!": {
|
"vecchietta|Salutaci i tuoi!": {
|
||||||
"file": "vecchietta-814e558af5.mp3",
|
"file": "vecchietta-814e558af5.mp3",
|
||||||
"sec": 1.47
|
"sec": 1.47
|
||||||
@@ -1451,6 +1591,74 @@
|
|||||||
"file": "vecchietto-c8eae2e59e.mp3",
|
"file": "vecchietto-c8eae2e59e.mp3",
|
||||||
"sec": 4.88
|
"sec": 4.88
|
||||||
},
|
},
|
||||||
|
"andrea|Ma che è sempre là, Borgo?": {
|
||||||
|
"file": "andrea-73c12c835b.mp3",
|
||||||
|
"sec": 2.34
|
||||||
|
},
|
||||||
|
"andrea|Come va alla Casa dell'Armando?": {
|
||||||
|
"file": "andrea-413cf7673b.mp3",
|
||||||
|
"sec": 1.56
|
||||||
|
},
|
||||||
|
"andrea|Ho trovato una squama del Regolo.": {
|
||||||
|
"file": "andrea-51314c3413.mp3",
|
||||||
|
"sec": 1.69
|
||||||
|
},
|
||||||
|
"andrea|Sotto la Fortezza ci sono le sue impronte.": {
|
||||||
|
"file": "andrea-898cf87dd0.mp3",
|
||||||
|
"sec": 2.49
|
||||||
|
},
|
||||||
|
"andrea|Ho la torcia. Stasera entro nella fessura.": {
|
||||||
|
"file": "andrea-343fb5c806.mp3",
|
||||||
|
"sec": 3.33
|
||||||
|
},
|
||||||
|
"andrea|Cosa stavamo dicendo???": {
|
||||||
|
"file": "andrea-06f5050907.mp3",
|
||||||
|
"sec": 1.24
|
||||||
|
},
|
||||||
|
"andrea|Ci si becca da i' Trappola, ai' Barrettino!": {
|
||||||
|
"file": "andrea-fca6f59a70.mp3",
|
||||||
|
"sec": 3.41
|
||||||
|
},
|
||||||
|
"arcu|E chi lo sposta???": {
|
||||||
|
"file": "arcu-64735a5925.mp3",
|
||||||
|
"sec": 0.97
|
||||||
|
},
|
||||||
|
"arcu|Mah... un si fa una sega...": {
|
||||||
|
"file": "arcu-5d07c15776.mp3",
|
||||||
|
"sec": 2.89
|
||||||
|
},
|
||||||
|
"arcu|Fammi vedere... Verde. Come la Panda di mi' zio.": {
|
||||||
|
"file": "arcu-af7afda339.mp3",
|
||||||
|
"sec": 4.18
|
||||||
|
},
|
||||||
|
"arcu|Verde! Allora il Regolo tifa Cardetole. Tradimento.": {
|
||||||
|
"file": "arcu-85c7d0b8f6.mp3",
|
||||||
|
"sec": 5.57
|
||||||
|
},
|
||||||
|
"arcu|E te ci vai da solo? Io ti aspetto qui.": {
|
||||||
|
"file": "arcu-e157a4b70b.mp3",
|
||||||
|
"sec": 2.73
|
||||||
|
},
|
||||||
|
"arcu|Qualcuno deve raccontarlo, dopo.": {
|
||||||
|
"file": "arcu-5d1fa73d32.mp3",
|
||||||
|
"sec": 1.77
|
||||||
|
},
|
||||||
|
"arcu|Fai una cosa: se vedi due occhi gialli, un sono i fari della Provinciale.": {
|
||||||
|
"file": "arcu-fdd1ab5f5b.mp3",
|
||||||
|
"sec": 4.37
|
||||||
|
},
|
||||||
|
"andrea|Grazie, Arcu. Molto utile.": {
|
||||||
|
"file": "andrea-2caf0f40f2.mp3",
|
||||||
|
"sec": 2.73
|
||||||
|
},
|
||||||
|
"andrea|Ma ti si è bruciata la memoria, fratello???!?": {
|
||||||
|
"file": "andrea-bf8a51895b.mp3",
|
||||||
|
"sec": 2.98
|
||||||
|
},
|
||||||
|
"arcu|...I pompieri per cosa?": {
|
||||||
|
"file": "arcu-5148dffe36.mp3",
|
||||||
|
"sec": 1.7
|
||||||
|
},
|
||||||
"andrea|Sono bloccato. Mi dai un consiglio?": {
|
"andrea|Sono bloccato. Mi dai un consiglio?": {
|
||||||
"file": "andrea-42b02eb9ea.mp3",
|
"file": "andrea-42b02eb9ea.mp3",
|
||||||
"sec": 3.9
|
"sec": 3.9
|
||||||
@@ -1527,6 +1735,42 @@
|
|||||||
"file": "castello-dc8a873d86.mp3",
|
"file": "castello-dc8a873d86.mp3",
|
||||||
"sec": 4.36
|
"sec": 4.36
|
||||||
},
|
},
|
||||||
|
"andrea|Laggiù, appoggiato al muro, c'è un angolo di tela dipinta: una strada bianca, e un omino con la maglia rossa e le braccia alzate.": {
|
||||||
|
"file": "andrea-6484641c58.mp3",
|
||||||
|
"sec": 8.67
|
||||||
|
},
|
||||||
|
"andrea|È il palio! Il quadro dei ragazzi delle medie!": {
|
||||||
|
"file": "andrea-51ec04c16e.mp3",
|
||||||
|
"sec": 3.54
|
||||||
|
},
|
||||||
|
"andrea|E quelli... sono due occhi gialli!": {
|
||||||
|
"file": "andrea-0f5f2a4b2f.mp3",
|
||||||
|
"sec": 2.63
|
||||||
|
},
|
||||||
|
"andrea|Spariti nel buio.": {
|
||||||
|
"file": "andrea-f34cc00733.mp3",
|
||||||
|
"sec": 1.17
|
||||||
|
},
|
||||||
|
"andrea|Il Regolo. E ha il nostro palio.": {
|
||||||
|
"file": "andrea-1b2601be96.mp3",
|
||||||
|
"sec": 2.77
|
||||||
|
},
|
||||||
|
"andrea|Però non l'ha portato via: l'ha messo proprio lassù, in Fortezza. Dove domani portiamo i mattoni col passamano.": {
|
||||||
|
"file": "andrea-abeac78e68.mp3",
|
||||||
|
"sec": 7.13
|
||||||
|
},
|
||||||
|
"andrea|Il palio è già pronto ad aspettarci. Torno giù a dirlo a tutti: la festa si fa!": {
|
||||||
|
"file": "andrea-28f672ef5f.mp3",
|
||||||
|
"sec": 5.42
|
||||||
|
},
|
||||||
|
"andrea|Mi ricordavo un finale diverso.": {
|
||||||
|
"file": "andrea-d9ff79ed54.mp3",
|
||||||
|
"sec": 1.73
|
||||||
|
},
|
||||||
|
"andrea|Il «Nulla» sta viaggiando troppo velocemente nell'animo umano, devo darmi una mossa!": {
|
||||||
|
"file": "andrea-71dc4628cc.mp3",
|
||||||
|
"sec": 4.81
|
||||||
|
},
|
||||||
"andrea|Niente di speciale.": {
|
"andrea|Niente di speciale.": {
|
||||||
"file": "andrea-6ebcf8e5de.mp3",
|
"file": "andrea-6ebcf8e5de.mp3",
|
||||||
"sec": 1.04
|
"sec": 1.04
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -90,3 +90,18 @@ si segna qui con la data e il punto di `src/story/story.js` dove sta; le persone
|
|||||||
gioco, come i nove bastioni.
|
gioco, come i nove bastioni.
|
||||||
- **Regole perché resti divertente**: le chiavi importanti non si buttano, una porta aperta resta aperta, al Trebbio
|
- **Regole perché resti divertente**: le chiavi importanti non si buttano, una porta aperta resta aperta, al Trebbio
|
||||||
c'è sempre l'aiuto.
|
c'è sempre l'aiuto.
|
||||||
|
- **Le mutande del Barone** (Andrea, 25 ottobre; ci pensa ancora): si ritrovano e gli si riportano, e lui in cambio
|
||||||
|
dà qualcosa che serve alla storia. Proposta: appese come trofeo all'insegna del circolino di Campomigliaio
|
||||||
|
(l'Arcu ci scherza), e in cambio due pile per la torcia della casetta, scarica.
|
||||||
|
- **La racchetta del Tozzino** (Andrea, 25 ottobre): non la trova, Federer sta arrivando, ha paura di perdere e chiede
|
||||||
|
aiuto ad Andrea. Si potrebbe legare al poker del Barone (persa la stessa sera?). Serve un foglio sprite del Tozzino
|
||||||
|
senza racchetta, più una posa con la racchetta ritrovata.
|
||||||
|
- **Consigli di Codex (25 ottobre), da valutare dopo 5 e 1 (risposte ai tentativi sbagliati e pettegolezzo che
|
||||||
|
cambia, fatti):**
|
||||||
|
- *Colpo di scena a metà*: la squama somiglia al Regolo della sfilata... ma allora chi ha lasciato le impronte?
|
||||||
|
Solo con dialoghi e una riga nel taccuino, senza toccare la catena degli enigmi.
|
||||||
|
- *Un enigma con l'Arcu*: tiene qualcosa, distrae qualcuno o fraintende un'istruzione (gag). Uno solo: tocca
|
||||||
|
soluzione, test, voci e la sua posizione in ogni scena dove compare (le pose ci sono).
|
||||||
|
- *Regia alla fessura*: col meccanismo del primo piano (`closeup`) il buio, la torcia, un istante di silenzio,
|
||||||
|
poi gli occhi. Due immagini di Codex.
|
||||||
|
- *Segreti facoltativi del paese* con pagine illustrate nel taccuino: funzione nuova, dopo la storia principale.
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
# Da dove vengono le immagini
|
# Da dove vengono le immagini
|
||||||
|
|
||||||
|
- `assets/closeups/palio-2007.jpg`: copia della foto `assets/raw/palio-2007-foto.jpg` fornita da Andrea
|
||||||
|
il 24 ottobre 2026. Usata nel primo piano della fessura; il renderer mostra soltanto la tela tramite
|
||||||
|
le coordinate `story.closeups.fessura.crop`, senza modificare la foto originale.
|
||||||
|
|
||||||
Da controllare **prima del primo push**: quello che è nella storia di git, una volta pubblicato, resta pubblico
|
Da controllare **prima del primo push**: quello che è nella storia di git, una volta pubblicato, resta pubblico
|
||||||
anche se poi lo si cancella. Le foto originali (`assets/raw/`) e i prompt (`prompts/`) sono esclusi da git e non sono
|
anche se poi lo si cancella. Le foto originali (`assets/raw/`) e i prompt (`prompts/`) sono esclusi da git e non sono
|
||||||
mai stati committati (verificato il 2026-10-23); qui si parla degli sfondi ridisegnati in `assets/scenes/`, che invece
|
mai stati committati (verificato il 2026-10-23); qui si parla degli sfondi ridisegnati in `assets/scenes/`, che invece
|
||||||
|
|||||||
@@ -18,6 +18,23 @@ Online su 50037.manzolo.it tutto fino agli effetti ambientali di Codex. Aperto,
|
|||||||
|
|
||||||
## Dove siamo arrivati
|
## Dove siamo arrivati
|
||||||
|
|
||||||
|
- **Multimedia (25 ottobre, modifiche locali)**: il libro sfogliabile già presente conserva immagini, battute e
|
||||||
|
riapertura dall'inventario; il fruscio ora segue il volume degli effetti, non quello delle voci.
|
||||||
|
Nuovi paesaggi sonori sintetizzati con Web Audio (`src/engine/soundscape.js`, profili in
|
||||||
|
`src/story/soundscapes.js`): vento, acqua, uccelli di giorno e grilli di sera, campane, bicchieri,
|
||||||
|
gocce e scricchiolii distanziati. In **Pausa → Ambiente ed effetti** si regola il volume, salvato nel browser.
|
||||||
|
Muto, pausa e pagina nascosta fermano anche i suoni già avviati.
|
||||||
|
La **torcia nella fessura** apre un primo piano: mouse, tocco/trascinamento o frecce spostano la luce;
|
||||||
|
Invio aiuta a cercare il prossimo dettaglio. Pietra → palio → occhi; la musica si abbassa durante la ricerca.
|
||||||
|
«Torna fuori»/Esc permette di riprovare; soltanto dopo gli occhi «Continua» avvia la conclusione.
|
||||||
|
Nessun progresso parziale viene salvato. La tela usa la foto vera del 2007, ritagliata durante il disegno.
|
||||||
|
Controllo mirato: `npm run browser -- --media-only`; il collaudo normale include anche queste prove.
|
||||||
|
Verificati `npm test` e `npm run browser`: soluzione completa, salvataggi, libro su desktop/telefono,
|
||||||
|
torcia con mouse/tastiera/tocco/trascinamento, pausa e muto, segnale Web Audio senza saturazione.
|
||||||
|
Schermate in `/tmp/regolo-shots/media-*.png` e `/tmp/regolo-shots/05b-fessura-*.png`.
|
||||||
|
I copioni video sono aggiornati ai gesti richiesti dalla torcia; il montaggio audio da file continua a
|
||||||
|
includere solo musica e voci (gli effetti Web Audio non vengono esportati dal copione).
|
||||||
|
|
||||||
- **Ambienti animati (25 ottobre)**: alle prove già presenti (bandiere del campeggio, fascio di luce nella Pieve,
|
- **Ambienti animati (25 ottobre)**: alle prove già presenti (bandiere del campeggio, fascio di luce nella Pieve,
|
||||||
ombre al Bosco ai Frati) si aggiungono 51 dettagli nelle altre 35 scene. Configurazione in
|
ombre al Bosco ai Frati) si aggiungono 51 dettagli nelle altre 35 scene. Configurazione in
|
||||||
`src/story/ambience.js`, richiamata da `story.js`; nuovi disegni in `src/engine/ambient.js`:
|
`src/story/ambience.js`, richiamata da `story.js`; nuovi disegni in `src/engine/ambient.js`:
|
||||||
|
|||||||
+5
-1
@@ -11,6 +11,7 @@
|
|||||||
<div id="stage">
|
<div id="stage">
|
||||||
<canvas id="scene" width="640" height="360" aria-label="La scena dell'avventura"></canvas>
|
<canvas id="scene" width="640" height="360" aria-label="La scena dell'avventura"></canvas>
|
||||||
<div id="speech" aria-live="polite"></div>
|
<div id="speech" aria-live="polite"></div>
|
||||||
|
<button id="closeup-close" hidden title="Chiudi (Esc)">Chiudi</button>
|
||||||
<div id="corner">
|
<div id="corner">
|
||||||
<button id="pause-button" hidden title="Pausa (Esc)">Pausa</button>
|
<button id="pause-button" hidden title="Pausa (Esc)">Pausa</button>
|
||||||
<button id="map-button" hidden title="Mappa (P)">Mappa</button>
|
<button id="map-button" hidden title="Mappa (P)">Mappa</button>
|
||||||
@@ -18,7 +19,7 @@
|
|||||||
<button id="spots-button" hidden title="Mostra cosa si può toccare (H)">?</button>
|
<button id="spots-button" hidden title="Mostra cosa si può toccare (H)">?</button>
|
||||||
</div>
|
</div>
|
||||||
<div id="sound">
|
<div id="sound">
|
||||||
<button id="mute" aria-label="Musica: togli l'audio" title="Musica (M)">♪</button>
|
<button id="mute" aria-label="Togli l'audio" title="Audio (M)">♪</button>
|
||||||
<input id="volume" type="range" min="0" max="100" step="5" aria-label="Volume della musica" title="Volume della musica">
|
<input id="volume" type="range" min="0" max="100" step="5" aria-label="Volume della musica" title="Volume della musica">
|
||||||
<label for="voice-volume" class="sound-label" title="Volume delle voci">bla</label>
|
<label for="voice-volume" class="sound-label" title="Volume delle voci">bla</label>
|
||||||
<input id="voice-volume" type="range" min="0" max="100" step="5" aria-label="Volume delle voci" title="Volume delle voci">
|
<input id="voice-volume" type="range" min="0" max="100" step="5" aria-label="Volume delle voci" title="Volume delle voci">
|
||||||
@@ -72,6 +73,9 @@
|
|||||||
</section>
|
</section>
|
||||||
<section id="pause" class="overlay" hidden aria-label="Pausa">
|
<section id="pause" class="overlay" hidden aria-label="Pausa">
|
||||||
<h2>Pausa</h2>
|
<h2>Pausa</h2>
|
||||||
|
<label class="effects-control" for="effects-volume">Ambiente ed effetti
|
||||||
|
<input id="effects-volume" type="range" min="0" max="100" step="5" aria-label="Volume ambiente ed effetti">
|
||||||
|
</label>
|
||||||
<div class="buttons pause-buttons">
|
<div class="buttons pause-buttons">
|
||||||
<button id="resume">Riprendi</button>
|
<button id="resume">Riprendi</button>
|
||||||
<button id="pause-map" class="secondary">Mappa</button>
|
<button id="pause-map" class="secondary">Mappa</button>
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "leggenda-del-regolo",
|
"name": "leggenda-del-regolo",
|
||||||
"version": "0.1.2",
|
"version": "0.1.5",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
+80
-3
@@ -22,6 +22,9 @@ const SPEED = 95;
|
|||||||
// Solo profilo, come i cicli di camminata: 'up' e 'down' lasciano il verso com'è.
|
// Solo profilo, come i cicli di camminata: 'up' e 'down' lasciano il verso com'è.
|
||||||
const FACING = { left: -1, right: 1 };
|
const FACING = { left: -1, right: 1 };
|
||||||
const WALK = ['walk_1', 'walk_2', 'walk_3', 'walk_4'], STEP = 15, REACH = 0.45;
|
const WALK = ['walk_1', 'walk_2', 'walk_3', 'walk_4'], STEP = 15, REACH = 0.45;
|
||||||
|
// Il primo piano di un libro (story.closeups, effetto `closeup`): copertina → frontespizio → una pagina girata →
|
||||||
|
// l'ultima pagina, poi dopo una pausa il commento. Tempi in secondi.
|
||||||
|
export const PAGE_TURN = 0.7, CLOSEUP_PAUSE = 1.4;
|
||||||
|
|
||||||
// Condizioni: 'flag', '!flag', 'has:oggetto', '!has:oggetto', oppure un elenco (tutte vere).
|
// Condizioni: 'flag', '!flag', 'has:oggetto', '!has:oggetto', oppure un elenco (tutte vere).
|
||||||
export function check(cond, state) {
|
export function check(cond, state) {
|
||||||
@@ -115,15 +118,16 @@ export class Game {
|
|||||||
this.hurry = false; // doppio clic: si cammina al doppio della velocità
|
this.hurry = false; // doppio clic: si cammina al doppio della velocità
|
||||||
this.reach = 0; // secondi di braccio teso quando prende qualcosa
|
this.reach = 0; // secondi di braccio teso quando prende qualcosa
|
||||||
this.back = false; // di spalle davanti a una porta o a una bacheca
|
this.back = false; // di spalle davanti a una porta o a una bacheca
|
||||||
|
this.closeup = null; // il primo piano aperto: { id, step: 'cover' | 'title' | 'turn' | 'end', t, age }
|
||||||
}
|
}
|
||||||
|
|
||||||
get scene() { return this.story.scenes[this.state.scene]; }
|
get scene() { return this.story.scenes[this.state.scene]; }
|
||||||
// Occupato: c'è qualcosa in corso che il giocatore non può interrompere. La camminata verso un punto
|
// Occupato: c'è qualcosa in corso che il giocatore non può interrompere. La camminata verso un punto
|
||||||
// o verso un oggetto si può sempre cambiare con un altro clic: la coda che la seguiva viene scartata.
|
// o verso un oggetto si può sempre cambiare con un altro clic: la coda che la seguiva viene scartata.
|
||||||
get busy() { return !!this.speech || this.reach > 0 || (this.task ? !this.task.interruptible : this.queue.length > 0); }
|
get busy() { return !!this.speech || !!this.closeup || this.reach > 0 || (this.task ? !this.task.interruptible : this.queue.length > 0); }
|
||||||
get idle() { return !this.busy && !this.task && !this.dialogue; }
|
get idle() { return !this.busy && !this.task && !this.dialogue; }
|
||||||
// Fermo: nessuna battuta, nessun effetto in coda, nessuna camminata che fa parte di una sequenza.
|
// Fermo: nessuna battuta, nessun effetto in coda, nessuna camminata che fa parte di una sequenza.
|
||||||
get steady() { return !this.speech && this.reach <= 0 && !this.queue.length && !(this.task && !this.task.interruptible); }
|
get steady() { return !this.speech && !this.closeup && this.reach <= 0 && !this.queue.length && !(this.task && !this.task.interruptible); }
|
||||||
// Lo stato da salvare adesso: quello attuale se è fermo, altrimenti l'ultimo punto fermo.
|
// Lo stato da salvare adesso: quello attuale se è fermo, altrimenti l'ultimo punto fermo.
|
||||||
savable() { return this.steady ? this.snapshot() : this.checkpoint; }
|
savable() { return this.steady ? this.snapshot() : this.checkpoint; }
|
||||||
// A sequenza finita, se qualcosa è cambiato, nuovo punto fermo e salvataggio.
|
// A sequenza finita, se qualcosa è cambiato, nuovo punto fermo e salvataggio.
|
||||||
@@ -221,6 +225,63 @@ export class Game {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Il primo piano: un tocco sfoglia (copertina → frontespizio → si gira la pagina); all'ultima pagina non fa niente.
|
||||||
|
closeupTap() {
|
||||||
|
const c = this.closeup;
|
||||||
|
if (!c || this.speech) return false;
|
||||||
|
if (this.story.closeups[c.id].type === 'torch') return false;
|
||||||
|
if (c.step === 'cover') Object.assign(c, { step: 'title', t: 0 });
|
||||||
|
else if (c.step === 'title') Object.assign(c, { step: 'turn', t: 0 });
|
||||||
|
else return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Chiuso il libro si torna alla scena, e gli effetti che seguivano il primo piano ripartono.
|
||||||
|
closeupClose() {
|
||||||
|
const c = this.closeup;
|
||||||
|
if (!c) return false;
|
||||||
|
this.closeup = null;
|
||||||
|
this.speech = null;
|
||||||
|
const def = this.story.closeups?.[c.id];
|
||||||
|
if (def?.type === 'torch') {
|
||||||
|
if (c.step === 'done') this.queue.unshift(...def.complete);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// Chi è arrivato all'ultima pagina, chiudendo, la commenta (`closing`).
|
||||||
|
if (c.step === 'end') this.queue.unshift(...(this.story.closeups?.[c.id]?.closing ?? []));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Solo luce, nessun clic sugli oggetti dietro al primo piano. Il progresso è transitorio:
|
||||||
|
// uscire o ricaricare durante la ricerca permette di ripeterla, senza anticipare il finale.
|
||||||
|
closeupAim([x, y]) {
|
||||||
|
const c = this.closeup;
|
||||||
|
if (!c || this.story.closeups[c.id].type !== 'torch' || !Number.isFinite(x) || !Number.isFinite(y)) return false;
|
||||||
|
c.beam = [Math.max(70, Math.min(570, x)), Math.max(65, Math.min(295, y))];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
updateTorch(dt) {
|
||||||
|
const c = this.closeup, def = this.story.closeups[c.id];
|
||||||
|
c.t += dt;
|
||||||
|
if (c.lines?.length) { this.run(c.lines.shift()); return; }
|
||||||
|
if (c.step === 'reveal') {
|
||||||
|
if (c.t < 1.4) return;
|
||||||
|
c.found++;
|
||||||
|
c.step = c.found === def.targets.length ? 'done' : 'search';
|
||||||
|
c.t = c.dwell = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const target = def.targets[c.found];
|
||||||
|
if (c.step !== 'search' || !target) return;
|
||||||
|
c.dwell = Math.hypot(c.beam[0] - target.at[0], c.beam[1] - target.at[1]) < target.radius ? c.dwell + dt : 0;
|
||||||
|
if (c.dwell >= 0.45) {
|
||||||
|
c.step = 'reveal';
|
||||||
|
c.t = 0;
|
||||||
|
c.lines = [...(target.lines ?? [])];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
options() {
|
options() {
|
||||||
if (!this.dialogue || this.busy) return [];
|
if (!this.dialogue || this.busy) return [];
|
||||||
const node = this.story.dialogues[this.dialogue.id].nodes[this.dialogue.node];
|
const node = this.story.dialogues[this.dialogue.id].nodes[this.dialogue.node];
|
||||||
@@ -271,6 +332,8 @@ export class Game {
|
|||||||
}
|
}
|
||||||
|
|
||||||
speakerPoint(who) {
|
speakerPoint(who) {
|
||||||
|
// Nel primo piano Andrea parla da sopra il libro, non dalla scena oscurata dietro.
|
||||||
|
if (this.closeup && (!who || who === 'andrea')) return [320, 34];
|
||||||
if (!who || who === 'andrea') return [this.state.x, this.state.y - 62 * this.scaleAt(this.state.y)];
|
if (!who || who === 'andrea') return [this.state.x, this.state.y - 62 * this.scaleAt(this.state.y)];
|
||||||
if (this.scene.speakers?.[who]) return this.scene.speakers[who];
|
if (this.scene.speakers?.[who]) return this.scene.speakers[who];
|
||||||
const h = this.hotspot(who) ?? (this.scene.hotspots ?? []).find(x => x.id === who);
|
const h = this.hotspot(who) ?? (this.scene.hotspots ?? []).find(x => x.id === who);
|
||||||
@@ -280,6 +343,7 @@ export class Game {
|
|||||||
|
|
||||||
update(dt) {
|
update(dt) {
|
||||||
this.time += dt;
|
this.time += dt;
|
||||||
|
if (this.closeup) this.closeup.age += dt;
|
||||||
if (this.speech) {
|
if (this.speech) {
|
||||||
this.speech.left -= dt;
|
this.speech.left -= dt;
|
||||||
if (this.speech.left > 0) return;
|
if (this.speech.left > 0) return;
|
||||||
@@ -310,8 +374,18 @@ export class Game {
|
|||||||
this.walking = false;
|
this.walking = false;
|
||||||
this.task = null;
|
this.task = null;
|
||||||
}
|
}
|
||||||
|
// Nel primo piano il tempo scorre solo per la pagina che gira e per la pausa prima del commento.
|
||||||
|
const c = this.closeup;
|
||||||
|
if (c) {
|
||||||
|
if (this.story.closeups[c.id].type === 'torch') { this.updateTorch(dt); return; }
|
||||||
|
c.t += dt;
|
||||||
|
if (c.step === 'turn' && c.t >= PAGE_TURN) Object.assign(c, { step: 'end', t: 0 });
|
||||||
|
if (c.step === 'end' && !c.lines && c.t >= CLOSEUP_PAUSE) c.lines = [...(this.story.closeups?.[c.id]?.comment ?? [])];
|
||||||
|
if (c.lines?.length) this.run(c.lines.shift());
|
||||||
|
return;
|
||||||
|
}
|
||||||
// Esegue gli effetti istantanei di fila e si ferma al primo che richiede tempo.
|
// Esegue gli effetti istantanei di fila e si ferma al primo che richiede tempo.
|
||||||
while (!this.speech && !this.walking && this.queue.length) this.run(this.queue.shift());
|
while (!this.speech && !this.walking && !this.closeup && this.queue.length) this.run(this.queue.shift());
|
||||||
this.commit();
|
this.commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -335,6 +409,9 @@ export class Game {
|
|||||||
else if (e.node) this.dialogue.node = e.node;
|
else if (e.node) this.dialogue.node = e.node;
|
||||||
else if (e.endDialogue) this.dialogue = null;
|
else if (e.endDialogue) this.dialogue = null;
|
||||||
else if (e.end) s.ended = true;
|
else if (e.end) s.ended = true;
|
||||||
|
else if (e.closeup) this.closeup = this.story.closeups[e.closeup].type === 'torch'
|
||||||
|
? { id: e.closeup, step: 'search', t: 0, age: 0, found: 0, dwell: 0, beam: [320, 180] }
|
||||||
|
: { id: e.closeup, step: 'cover', t: 0, age: 0 };
|
||||||
else throw new Error('Effetto sconosciuto: ' + JSON.stringify(e));
|
else throw new Error('Effetto sconosciuto: ' + JSON.stringify(e));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+86
-1
@@ -1,7 +1,8 @@
|
|||||||
// Disegno della scena su un canvas 640×360, ingrandito dal CSS senza sfocatura.
|
// Disegno della scena su un canvas 640×360, ingrandito dal CSS senza sfocatura.
|
||||||
// Le forme provvisorie (`art`) verranno sostituite da sfondi e sprite in pixel art.
|
// Le forme provvisorie (`art`) verranno sostituite da sfondi e sprite in pixel art.
|
||||||
import { check } from './game.js';
|
import { check, PAGE_TURN } from './game.js';
|
||||||
import { ambientEffects, ambientHash } from './ambient.js';
|
import { ambientEffects, ambientHash } from './ambient.js';
|
||||||
|
import { drawTorch } from './torch.js';
|
||||||
import { versioned } from '../version.js';
|
import { versioned } from '../version.js';
|
||||||
export const WIDTH = 640, HEIGHT = 360;
|
export const WIDTH = 640, HEIGHT = 360;
|
||||||
|
|
||||||
@@ -170,6 +171,7 @@ export function render(ctx, game, { hover, spots, debug, time = performance.now(
|
|||||||
drawLights(ctx, game, time);
|
drawLights(ctx, game, time);
|
||||||
for (const shape of art) if (shape.top) drawShape(ctx, shape);
|
for (const shape of art) if (shape.top) drawShape(ctx, shape);
|
||||||
if (spots) drawSpots(ctx, game);
|
if (spots) drawSpots(ctx, game);
|
||||||
|
if (game.closeup) drawCloseup(ctx, game, time);
|
||||||
if (debug) drawDebug(ctx, game, debug);
|
if (debug) drawDebug(ctx, game, debug);
|
||||||
if (hover) {
|
if (hover) {
|
||||||
ctx.strokeStyle = 'rgba(255,255,255,0.35)';
|
ctx.strokeStyle = 'rgba(255,255,255,0.35)';
|
||||||
@@ -644,3 +646,86 @@ function drawDebug(ctx, game, { mouse, points = [], help }) {
|
|||||||
label(`${game.state.scene} ${where} ${help ?? ''}`, 2, HEIGHT - 3, '#fff');
|
label(`${game.state.scene} ${where} ${help ?? ''}`, 2, HEIGHT - 3, '#fff');
|
||||||
ctx.restore();
|
ctx.restore();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --- Il primo piano di un libro (story.closeups, game.closeup): la scena si oscura, le mani alzano il libro dal basso.
|
||||||
|
// Le immagini hanno etichetta e pagine vuote: i testi si scrivono qui, nitidi. Una pagina sola gira, a fisarmonica
|
||||||
|
// sulla piega; sotto c'è già l'ultima pagina.
|
||||||
|
const ink = '#3a1f12', FONT = '"Press Start 2P", monospace';
|
||||||
|
function pageText(ctx, lines, [x, y, w, h], size, at = 0.5, color = ink) {
|
||||||
|
ctx.font = `${size}px ${FONT}`;
|
||||||
|
ctx.textAlign = 'center';
|
||||||
|
ctx.textBaseline = 'middle';
|
||||||
|
ctx.fillStyle = color;
|
||||||
|
const gap = size * 1.7, top = y + h * at - (lines.length - 1) * gap / 2;
|
||||||
|
lines.forEach((line, i) => ctx.fillText(line, Math.round(x + w / 2), Math.round(top + i * gap)));
|
||||||
|
}
|
||||||
|
const twoLines = title => { const i = title.lastIndexOf(' '); return i > 0 ? [title.slice(0, i), title.slice(i + 1)] : [title]; };
|
||||||
|
|
||||||
|
function drawCloseup(ctx, game, time) {
|
||||||
|
const c = game.closeup, def = game.story.closeups?.[c.id];
|
||||||
|
if (!def) return;
|
||||||
|
if (def.type === 'torch') {
|
||||||
|
if (!backgrounds.has(def.picture)) loadBackground(def.picture);
|
||||||
|
drawTorch(ctx, c, def, backgrounds.get(def.picture));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ctx.save();
|
||||||
|
ctx.fillStyle = `rgba(8, 5, 12, ${Math.min(0.78, c.age / 0.35 * 0.78)})`;
|
||||||
|
ctx.fillRect(0, 0, WIDTH, HEIGHT);
|
||||||
|
const src = c.step === 'cover' ? def.closed : def.open, img = backgrounds.get(src);
|
||||||
|
if (!img) { loadBackground(src); loadBackground(c.step === 'cover' ? def.open : def.closed); ctx.restore(); return; }
|
||||||
|
// Il libro sale dal basso (solo all'inizio), con le braccia che entrano dal bordo.
|
||||||
|
const rise = 1 - Math.min(1, c.age / 0.45), ox = Math.round((WIDTH - img.width) / 2);
|
||||||
|
const oy = Math.round(HEIGHT - img.height + 140 * rise * rise);
|
||||||
|
ctx.imageSmoothingEnabled = false;
|
||||||
|
ctx.drawImage(img, ox, oy);
|
||||||
|
ctx.translate(ox, oy);
|
||||||
|
const lines = twoLines(def.title), { left, right, spine } = def.pages;
|
||||||
|
if (c.step === 'cover') pageText(ctx, lines, def.label, 8);
|
||||||
|
else {
|
||||||
|
const flip = c.step === 'turn' ? Math.min(1, c.t / PAGE_TURN) : c.step === 'end' ? 1 : 0;
|
||||||
|
// Sotto la pagina che gira c'è già l'ultima: «FINE», e nient'altro.
|
||||||
|
if (flip > 0) pageText(ctx, [def.last], right, 20, 0.46);
|
||||||
|
else pageText(ctx, lines, right, 8, 0.32);
|
||||||
|
if (flip > 0 && flip < 1) {
|
||||||
|
// La pagina che gira: si stringe sulla piega e passa a sinistra, col dorso un po' più scuro.
|
||||||
|
const e = (1 - Math.cos(Math.PI * flip)) / 2, k = Math.cos(Math.PI * e);
|
||||||
|
const lift = Math.round(Math.sin(Math.PI * e) * 10), [, y, , h] = right, pw = right[0] + right[2] - spine;
|
||||||
|
ctx.save();
|
||||||
|
ctx.translate(spine, 0);
|
||||||
|
ctx.scale(k || 0.001, 1);
|
||||||
|
ctx.fillStyle = k > 0 ? def.paper : '#e6cc9c';
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.moveTo(0, y); ctx.lineTo(pw, y - lift); ctx.lineTo(pw, y + h - lift); ctx.lineTo(0, y + h);
|
||||||
|
ctx.closePath();
|
||||||
|
ctx.fill();
|
||||||
|
ctx.strokeStyle = 'rgba(58, 31, 18, 0.55)';
|
||||||
|
ctx.lineWidth = 1 / Math.max(0.2, Math.abs(k));
|
||||||
|
ctx.stroke();
|
||||||
|
if (k > 0) pageText(ctx, lines, [right[0] - spine, y - lift, right[2], h], 8, 0.32);
|
||||||
|
ctx.restore();
|
||||||
|
}
|
||||||
|
// Dove toccare per sfogliare: l'angolo della pagina che pulsa.
|
||||||
|
if (c.step === 'title' && !game.speech) {
|
||||||
|
const pulse = 0.5 + 0.5 * Math.sin(time / 260), cx = right[0] + right[2] - 2, cy = right[1] + right[3] - 2, d = 12 + 3 * pulse;
|
||||||
|
ctx.fillStyle = `rgba(232, 194, 90, ${0.55 + 0.4 * pulse})`;
|
||||||
|
ctx.beginPath(); ctx.moveTo(cx, cy); ctx.lineTo(cx - d, cy); ctx.lineTo(cx, cy - d); ctx.closePath(); ctx.fill();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ctx.restore();
|
||||||
|
// Il suggerimento in alto, finché c'è qualcosa da sfogliare.
|
||||||
|
const hint = c.step === 'cover' ? 'Clic o tocco: apri il libro' : c.step === 'title' ? 'Clic o tocco: gira la pagina' : null;
|
||||||
|
if (hint && !game.speech && c.age > 0.5) {
|
||||||
|
ctx.save();
|
||||||
|
ctx.globalAlpha = 0.65 + 0.35 * Math.sin(time / 300);
|
||||||
|
ctx.font = `7px ${FONT}`;
|
||||||
|
ctx.textAlign = 'center';
|
||||||
|
ctx.textBaseline = 'middle';
|
||||||
|
ctx.fillStyle = 'rgba(0, 0, 0, 0.6)';
|
||||||
|
const tw = ctx.measureText(hint).width;
|
||||||
|
ctx.fillRect(WIDTH / 2 - tw / 2 - 6, 8, tw + 12, 14);
|
||||||
|
ctx.fillStyle = '#ffd27a';
|
||||||
|
ctx.fillText(hint, WIDTH / 2, 15);
|
||||||
|
ctx.restore();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user