Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fbeef76f01 | ||
|
|
45d310b9b4 | ||
|
|
481e4a9514 | ||
|
|
fde68603cb | ||
|
|
686fee043e | ||
|
|
4b709ffd80 | ||
|
|
733680301c | ||
|
|
0ba8cfc800 |
|
After Width: | Height: | Size: 316 KiB |
|
After Width: | Height: | Size: 5.9 KiB |
|
After Width: | Height: | Size: 5.6 KiB |
|
After Width: | Height: | Size: 6.0 KiB |
|
After Width: | Height: | Size: 5.4 KiB |
|
After Width: | Height: | Size: 6.3 KiB |
|
After Width: | Height: | Size: 5.9 KiB |
|
After Width: | Height: | Size: 5.1 KiB |
|
After Width: | Height: | Size: 5.1 KiB |
|
After Width: | Height: | Size: 4.9 KiB |
|
After Width: | Height: | Size: 5.3 KiB |
|
After Width: | Height: | Size: 5.1 KiB |
|
After Width: | Height: | Size: 4.9 KiB |
|
After Width: | Height: | Size: 4.7 KiB |
|
After Width: | Height: | Size: 5.3 KiB |
|
After Width: | Height: | Size: 5.3 KiB |
|
After Width: | Height: | Size: 452 KiB |
|
After Width: | Height: | Size: 419 KiB |
|
After Width: | Height: | Size: 464 KiB |
|
After Width: | Height: | Size: 352 KiB |
|
After Width: | Height: | Size: 447 KiB |
|
After Width: | Height: | Size: 454 KiB |
|
After Width: | Height: | Size: 328 KiB |
|
After Width: | Height: | Size: 320 KiB |
|
After Width: | Height: | Size: 222 KiB |
|
After Width: | Height: | Size: 331 KiB |
|
After Width: | Height: | Size: 324 KiB |
|
After Width: | Height: | Size: 275 KiB |
|
After Width: | Height: | Size: 184 KiB |
|
After Width: | Height: | Size: 290 KiB |
@@ -95,6 +95,10 @@
|
|||||||
"file": "andrea-a9df2e6bbb.mp3",
|
"file": "andrea-a9df2e6bbb.mp3",
|
||||||
"sec": 4.98
|
"sec": 4.98
|
||||||
},
|
},
|
||||||
|
"andrea|La bottega di Pierin di Frilli, sotto la tenda rossa. Da ragazzi ci si comprava lo stucco per la cerbottana.": {
|
||||||
|
"file": "andrea-cb15f8f919.mp3",
|
||||||
|
"sec": 7.29
|
||||||
|
},
|
||||||
"andrea|Il Circolo 4 Maggio. Dentro, dietro il bar, la sala dei biliardi: tre tavoli e il silenzio delle grandi occasioni.": {
|
"andrea|Il Circolo 4 Maggio. Dentro, dietro il bar, la sala dei biliardi: tre tavoli e il silenzio delle grandi occasioni.": {
|
||||||
"file": "andrea-f0aef83c80.mp3",
|
"file": "andrea-f0aef83c80.mp3",
|
||||||
"sec": 9.43
|
"sec": 9.43
|
||||||
@@ -1640,12 +1644,16 @@
|
|||||||
"sec": 4.82
|
"sec": 4.82
|
||||||
},
|
},
|
||||||
"andrea|Lo zio Mario. Guarda il muro, guarda la macchina, e si gratta la testa sotto il berretto.": {
|
"andrea|Lo zio Mario. Guarda il muro, guarda la macchina, e si gratta la testa sotto il berretto.": {
|
||||||
"file": "andrea-759a969d58.mp3",
|
"file": "andrea-9da3d936d3.mp3",
|
||||||
"sec": 6.69
|
"sec": 6.14
|
||||||
},
|
},
|
||||||
"andrea|Lo lascio pensare: quando ha trovato il modo di tirarla fuori, me lo dice lui.": {
|
"andrea|Zio, hai problemi?": {
|
||||||
"file": "andrea-84ff10b5f4.mp3",
|
"file": "andrea-c36f0dd2c5.mp3",
|
||||||
"sec": 4.86
|
"sec": 1.52
|
||||||
|
},
|
||||||
|
"zio_mario|I problemi io gli avevo quando andavo a scuola!": {
|
||||||
|
"file": "zio_mario-b3e99c241a.mp3",
|
||||||
|
"sec": 2.68
|
||||||
},
|
},
|
||||||
"andrea|Il parcheggio sotto casa. Col gesso ci si disegnava la pista delle macchinine, e si giocava finché non chiamavano per cena.": {
|
"andrea|Il parcheggio sotto casa. Col gesso ci si disegnava la pista delle macchinine, e si giocava finché non chiamavano per cena.": {
|
||||||
"file": "andrea-8670e6ce99.mp3",
|
"file": "andrea-8670e6ce99.mp3",
|
||||||
@@ -1655,10 +1663,6 @@
|
|||||||
"file": "andrea-6c9e7f684e.mp3",
|
"file": "andrea-6c9e7f684e.mp3",
|
||||||
"sec": 8.72
|
"sec": 8.72
|
||||||
},
|
},
|
||||||
"andrea|Se salgo, mi mettono ad apparecchiare. Prima il palio.": {
|
|
||||||
"file": "andrea-8945f1786d.mp3",
|
|
||||||
"sec": 3.89
|
|
||||||
},
|
|
||||||
"andrea|Il prato sotto casa. Qui le porte le facevamo con le maglie per terra: due maglie, un palo ciascuna.": {
|
"andrea|Il prato sotto casa. Qui le porte le facevamo con le maglie per terra: due maglie, un palo ciascuna.": {
|
||||||
"file": "andrea-4708fda5ef.mp3",
|
"file": "andrea-4708fda5ef.mp3",
|
||||||
"sec": 6.92
|
"sec": 6.92
|
||||||
@@ -1683,6 +1687,190 @@
|
|||||||
"file": "andrea-8d5911c8e7.mp3",
|
"file": "andrea-8d5911c8e7.mp3",
|
||||||
"sec": 4.53
|
"sec": 4.53
|
||||||
},
|
},
|
||||||
|
"andrea|La vista di casa. Da qui si vede mezzo paese, e lassù la Fortezza.": {
|
||||||
|
"file": "andrea-8a63e250ae.mp3",
|
||||||
|
"sec": 5.64
|
||||||
|
},
|
||||||
|
"andrea|Lassù in cima, fra gli alberi, la Fortezza. Da qui pare piccina.": {
|
||||||
|
"file": "andrea-6544c0d778.mp3",
|
||||||
|
"sec": 6.17
|
||||||
|
},
|
||||||
|
"andrea|Il paese che sale verso la collina, coi tetti uno sull'altro e il campanile in mezzo.": {
|
||||||
|
"file": "andrea-b082638d5a.mp3",
|
||||||
|
"sec": 5.93
|
||||||
|
},
|
||||||
|
"andrea|Il palazzo accanto, di mattoni come il nostro.": {
|
||||||
|
"file": "andrea-8d0507f514.mp3",
|
||||||
|
"sec": 2.45
|
||||||
|
},
|
||||||
|
"andrea|I gerani. Guai a chi li tocca.": {
|
||||||
|
"file": "andrea-54d8dfd381.mp3",
|
||||||
|
"sec": 2.86
|
||||||
|
},
|
||||||
|
"andrea|Se ne strappo uno, il palio lo guardo dal letto.": {
|
||||||
|
"file": "andrea-02fe387f5d.mp3",
|
||||||
|
"sec": 3.45
|
||||||
|
},
|
||||||
|
"andrea|L'edera nel vaso: cresce da sola, e si arrampica dove le pare.": {
|
||||||
|
"file": "andrea-ab2bb4cae8.mp3",
|
||||||
|
"sec": 4.68
|
||||||
|
},
|
||||||
|
"andrea|Una sedia di plastica, piegata.": {
|
||||||
|
"file": "andrea-8b314f556d.mp3",
|
||||||
|
"sec": 2.05
|
||||||
|
},
|
||||||
|
"andrea|Sedermi qui a guardare il paese? Prima il palio.": {
|
||||||
|
"file": "andrea-7593ef5d63.mp3",
|
||||||
|
"sec": 3.41
|
||||||
|
},
|
||||||
|
"andrea|La porta-finestra di casa, con la tapparella a metà.": {
|
||||||
|
"file": "andrea-be7c2b9a45.mp3",
|
||||||
|
"sec": 3.16
|
||||||
|
},
|
||||||
|
"andrea|Se rientro, mi mettono ad apparecchiare. Prima il palio.": {
|
||||||
|
"file": "andrea-2e64b2d5c2.mp3",
|
||||||
|
"sec": 4.8
|
||||||
|
},
|
||||||
|
"andrea|Un piccolo stemma di pietra sul muro. Chissà di chi era, questa casa, un tempo.": {
|
||||||
|
"file": "andrea-9317777d3a.mp3",
|
||||||
|
"sec": 4.94
|
||||||
|
},
|
||||||
|
"andrea|Il lampione di ferro, attaccato al muro. La sera fa una luce gialla che pare d'altri tempi.": {
|
||||||
|
"file": "andrea-e400e4ea1d.mp3",
|
||||||
|
"sec": 6.11
|
||||||
|
},
|
||||||
|
"andrea|La palestra della scuola, col tetto a denti di sega.": {
|
||||||
|
"file": "andrea-5ed0615726.mp3",
|
||||||
|
"sec": 3.13
|
||||||
|
},
|
||||||
|
"andrea|Lassù Monte Cacioli, con le antenne in cima.": {
|
||||||
|
"file": "andrea-c633ffc747.mp3",
|
||||||
|
"sec": 3.12
|
||||||
|
},
|
||||||
|
"andrea|Una siepe alta come una casa, e l'edera che si mangia il muro.": {
|
||||||
|
"file": "andrea-2544c4c379.mp3",
|
||||||
|
"sec": 3.89
|
||||||
|
},
|
||||||
|
"andrea|Le villette col giardino e il muretto: qui è tutto in ordine.": {
|
||||||
|
"file": "andrea-05ade48460.mp3",
|
||||||
|
"sec": 4.36
|
||||||
|
},
|
||||||
|
"andrea|Una villa con gli archi dietro la siepe. Qui le siepi le tosano col righello.": {
|
||||||
|
"file": "andrea-2e0acd9298.mp3",
|
||||||
|
"sec": 5
|
||||||
|
},
|
||||||
|
"andrea|Un cipresso dritto come un fuso, in mezzo all'aiuola.": {
|
||||||
|
"file": "andrea-33576f81c3.mp3",
|
||||||
|
"sec": 3.8
|
||||||
|
},
|
||||||
|
"andrea|Una panchina all'ombra.": {
|
||||||
|
"file": "andrea-ee2789a3a8.mp3",
|
||||||
|
"sec": 1.38
|
||||||
|
},
|
||||||
|
"andrea|Sedersi ora? Prima il palio.": {
|
||||||
|
"file": "andrea-aa636ddf94.mp3",
|
||||||
|
"sec": 2.74
|
||||||
|
},
|
||||||
|
"andrea|Il palazzo di mattoni coi negozi sotto, di là dalla Provinciale.": {
|
||||||
|
"file": "andrea-211109ca9d.mp3",
|
||||||
|
"sec": 4.66
|
||||||
|
},
|
||||||
|
"andrea|I platani della Provinciale: d'estate fanno un'ombra che pare una galleria.": {
|
||||||
|
"file": "andrea-2ce9db22c9.mp3",
|
||||||
|
"sec": 5.8
|
||||||
|
},
|
||||||
|
"andrea|Le villette sotto il bosco, coi giardini curati.": {
|
||||||
|
"file": "andrea-402f9ec788.mp3",
|
||||||
|
"sec": 3.1
|
||||||
|
},
|
||||||
|
"andrea|La cascatella della Carza: quella che si vede anche dalla Luna.": {
|
||||||
|
"file": "andrea-e9bb43952d.mp3",
|
||||||
|
"sec": 3.42
|
||||||
|
},
|
||||||
|
"andrea|D'estate si veniva a rinfrescare i piedi qui sotto.": {
|
||||||
|
"file": "andrea-2d8e58541c.mp3",
|
||||||
|
"sec": 2.96
|
||||||
|
},
|
||||||
|
"andrea|Il greto pieno di sassi. Dighe, ponti, pesci immaginari: qui ci si passava l'estate.": {
|
||||||
|
"file": "andrea-816bf4c405.mp3",
|
||||||
|
"sec": 8.38
|
||||||
|
},
|
||||||
|
"andrea|Un lampione in mezzo al prato. Di sera la passeggiata la fanno le zanzare.": {
|
||||||
|
"file": "andrea-74fe2ee88c.mp3",
|
||||||
|
"sec": 5.16
|
||||||
|
},
|
||||||
|
"andrea|Gli orti con la rete: cavoli, insalata e i fagioli sulle canne.": {
|
||||||
|
"file": "andrea-343e479437.mp3",
|
||||||
|
"sec": 5.4
|
||||||
|
},
|
||||||
|
"andrea|Un cavolo dall'orto di qualcun altro? Poi chi lo sente.": {
|
||||||
|
"file": "andrea-e842495cf5.mp3",
|
||||||
|
"sec": 4.17
|
||||||
|
},
|
||||||
|
"andrea|Un ponticino di ferro sul fosso. Due passi e sei di là.": {
|
||||||
|
"file": "andrea-145bc6ff82.mp3",
|
||||||
|
"sec": 4.21
|
||||||
|
},
|
||||||
|
"andrea|Il greto bianco della Carza, con un filo d'acqua in mezzo ai sassi.": {
|
||||||
|
"file": "andrea-f2902ed3cd.mp3",
|
||||||
|
"sec": 3.72
|
||||||
|
},
|
||||||
|
"andrea|Una casa con la siepe rossa davanti. Da quel balcone si vede tutta la Carza.": {
|
||||||
|
"file": "andrea-4d4c45e5de.mp3",
|
||||||
|
"sec": 6.26
|
||||||
|
},
|
||||||
|
"andrea|La Carza sotto il muretto, con le canne dritte nell'acqua e il muro vecchio di sassi.": {
|
||||||
|
"file": "andrea-bcce90bf03.mp3",
|
||||||
|
"sec": 5.65
|
||||||
|
},
|
||||||
|
"andrea|Gli orti fatti coi bancali e le cassette, il bidone blu per l'acqua. Ognuno a modo suo.": {
|
||||||
|
"file": "andrea-5c7774bb32.mp3",
|
||||||
|
"sec": 7.15
|
||||||
|
},
|
||||||
|
"andrea|Qui la Carza ha un po' d'acqua chiara fra i sassi bianchi.": {
|
||||||
|
"file": "andrea-0a363e408f.mp3",
|
||||||
|
"sec": 3.63
|
||||||
|
},
|
||||||
|
"andrea|Il ponte delle poste, coi suoi tre archi di mattoni: da sotto pare più vecchio del paese.": {
|
||||||
|
"file": "andrea-1e782b31f7.mp3",
|
||||||
|
"sec": 5.87
|
||||||
|
},
|
||||||
|
"andrea|Altri orti, coi cavoli grossi come palloni.": {
|
||||||
|
"file": "andrea-dc196f39fc.mp3",
|
||||||
|
"sec": 3.41
|
||||||
|
},
|
||||||
|
"andrea|La Carza passa sotto gli archi e se ne va verso la Sieve.": {
|
||||||
|
"file": "andrea-33a6033e4f.mp3",
|
||||||
|
"sec": 3.16
|
||||||
|
},
|
||||||
|
"andrea|La casa dello zio Mario, quella gialla al sole.": {
|
||||||
|
"file": "andrea-d641627592.mp3",
|
||||||
|
"sec": 3.18
|
||||||
|
},
|
||||||
|
"andrea|Gli orti dello zio Mario: pomodori sulle canne, insalata, cavoli. Tutto in fila come soldati.": {
|
||||||
|
"file": "andrea-9fd392ca78.mp3",
|
||||||
|
"sec": 7.46
|
||||||
|
},
|
||||||
|
"andrea|Un pomodoro dell'orto dello zio? Se se ne accorge, e se ne accorge, son dolori.": {
|
||||||
|
"file": "andrea-1f05d7a7da.mp3",
|
||||||
|
"sec": 6.16
|
||||||
|
},
|
||||||
|
"andrea|Laggiù la passerella coperta sulla Carza.": {
|
||||||
|
"file": "andrea-42e8b1e2b0.mp3",
|
||||||
|
"sec": 2.81
|
||||||
|
},
|
||||||
|
"andrea|Di là ci passo un'altra volta: prima il palio.": {
|
||||||
|
"file": "andrea-d38b6e49ef.mp3",
|
||||||
|
"sec": 3.49
|
||||||
|
},
|
||||||
|
"andrea|Le case coi balconi pieni di vasi: qui ogni finestra è un giardino.": {
|
||||||
|
"file": "andrea-ec81875c47.mp3",
|
||||||
|
"sec": 5.22
|
||||||
|
},
|
||||||
|
"andrea|Il palazzo di mattoni e intonaco, coi balconi in fila.": {
|
||||||
|
"file": "andrea-d32e1a2a87.mp3",
|
||||||
|
"sec": 3.45
|
||||||
|
},
|
||||||
"andrea|Un pino a ombrello enorme. Alla ricreazione, tutti all'ombra lì sotto. Sembra ieri.": {
|
"andrea|Un pino a ombrello enorme. Alla ricreazione, tutti all'ombra lì sotto. Sembra ieri.": {
|
||||||
"file": "andrea-0a073729fd.mp3",
|
"file": "andrea-0a073729fd.mp3",
|
||||||
"sec": 7.3
|
"sec": 7.3
|
||||||
@@ -2228,8 +2416,8 @@
|
|||||||
"sec": 4.42
|
"sec": 4.42
|
||||||
},
|
},
|
||||||
"arcu|Fammi vedere... Verde. Come la Panda di mi' zio.": {
|
"arcu|Fammi vedere... Verde. Come la Panda di mi' zio.": {
|
||||||
"file": "arcu-62e981592d.mp3",
|
"file": "arcu-82526ee9fb.mp3",
|
||||||
"sec": 6.29
|
"sec": 4.52
|
||||||
},
|
},
|
||||||
"arcu|Verde! Allora il Regolo tifa Cardetole. Tradimento.": {
|
"arcu|Verde! Allora il Regolo tifa Cardetole. Tradimento.": {
|
||||||
"file": "arcu-9e5b7c6e95.mp3",
|
"file": "arcu-9e5b7c6e95.mp3",
|
||||||
@@ -2443,6 +2631,26 @@
|
|||||||
"file": "mariano-d65fb6e871.mp3",
|
"file": "mariano-d65fb6e871.mp3",
|
||||||
"sec": 3.42
|
"sec": 3.42
|
||||||
},
|
},
|
||||||
|
"andrea|Una cerbottana e un po' di stucco, Pierino!": {
|
||||||
|
"file": "andrea-eaaf19eef0.mp3",
|
||||||
|
"sec": 2.77
|
||||||
|
},
|
||||||
|
"andrea|Niente, grazie: guardavo.": {
|
||||||
|
"file": "andrea-12cbe6f9a8.mp3",
|
||||||
|
"sec": 2.26
|
||||||
|
},
|
||||||
|
"andrea|Lo stucco verde di Pierino: quell'odore non te lo levi più dalle dita.": {
|
||||||
|
"file": "andrea-2ede7e7324.mp3",
|
||||||
|
"sec": 3.82
|
||||||
|
},
|
||||||
|
"andrea|Ora un muro. Quello della piazza va benissimo.": {
|
||||||
|
"file": "andrea-9cc0991d39.mp3",
|
||||||
|
"sec": 3.32
|
||||||
|
},
|
||||||
|
"andrea|No, dopo.": {
|
||||||
|
"file": "andrea-78ad61a67a.mp3",
|
||||||
|
"sec": 1.22
|
||||||
|
},
|
||||||
"andrea|Si fa una gara alle macchinine?!?!": {
|
"andrea|Si fa una gara alle macchinine?!?!": {
|
||||||
"file": "andrea-17216997e2.mp3",
|
"file": "andrea-17216997e2.mp3",
|
||||||
"sec": 2.74
|
"sec": 2.74
|
||||||
@@ -2859,6 +3067,18 @@
|
|||||||
"file": "bertovo-ca941bee91.mp3",
|
"file": "bertovo-ca941bee91.mp3",
|
||||||
"sec": 5.41
|
"sec": 5.41
|
||||||
},
|
},
|
||||||
|
"andrea|Tutti sul muro, verdi in fila. Lo stucco di Pierino un tradisce mai.": {
|
||||||
|
"file": "andrea-585cd65f93.mp3",
|
||||||
|
"sec": 5.2
|
||||||
|
},
|
||||||
|
"andrea|Finito lo stucco. Domani si ripassa da Pierino.": {
|
||||||
|
"file": "andrea-62c5d74b82.mp3",
|
||||||
|
"sec": 3.29
|
||||||
|
},
|
||||||
|
"andrea|Il muro resta lì. E l'odore dello stucco, sulle dita, pure.": {
|
||||||
|
"file": "andrea-c7dcb11e66.mp3",
|
||||||
|
"sec": 5.52
|
||||||
|
},
|
||||||
"chiaru|Hai vinto te. Ma la mia aveva le ruote piene di gesso, sia chiaro.": {
|
"chiaru|Hai vinto te. Ma la mia aveva le ruote piene di gesso, sia chiaro.": {
|
||||||
"file": "chiaru-91a4b23b22.mp3",
|
"file": "chiaru-91a4b23b22.mp3",
|
||||||
"sec": 4.44
|
"sec": 4.44
|
||||||
|
|||||||
@@ -33,6 +33,8 @@ ne è un'opera derivata. Le foto scattate da Andrea non hanno problemi; quelle p
|
|||||||
| `characters/chiaru.png` | Codex | `foto/chiaru.jpg` | Andrea (29 ottobre) | sì (il Chiaru consenziente) |
|
| `characters/chiaru.png` | Codex | `foto/chiaru.jpg` | Andrea (29 ottobre) | sì (il Chiaru consenziente) |
|
||||||
| `via-liguri-magelli-muro.png` | Codex, ritocco di `via-liguri-magelli.png` con la Ghiacciomobile nel muro | come `via-liguri-magelli.png` | Street View | **no**: come lo sfondo da cui viene |
|
| `via-liguri-magelli-muro.png` | Codex, ritocco di `via-liguri-magelli.png` con la Ghiacciomobile nel muro | come `via-liguri-magelli.png` | Street View | **no**: come lo sfondo da cui viene |
|
||||||
| `characters/zio_mario.png` | Codex | `foto/zio-mario.png` | Andrea (29 ottobre) | sì (famiglia di Andrea) |
|
| `characters/zio_mario.png` | Codex | `foto/zio-mario.png` | Andrea (29 ottobre) | sì (famiglia di Andrea) |
|
||||||
|
| `terrazza-cardetole.png` | Codex (dalla foto, poi il terrazzo davanti) | `cardetole-finestra.jpg` | Andrea (29 ottobre) | **da decidere**: come `cardetole.png`, dice dove abita Andrea |
|
||||||
|
| `closeups/muro-cerbottana.png` | Codex, solo testo (stile dalla piazza) | nessuna | — | sì |
|
||||||
| `cardetole.png` | Codex | `cardetole.jpg` | Andrea (EXIF) | **da decidere**: è la casa vera di Andrea, pubblicarla dice dove abita |
|
| `cardetole.png` | Codex | `cardetole.jpg` | Andrea (EXIF) | **da decidere**: è la casa vera di Andrea, pubblicarla dice dove abita |
|
||||||
| `pieve-interno.png` | Codex | `pieve-interno.png` | Mariano Mirannalti (mandata ad Andrea su WhatsApp) | sì, se Mariano è d'accordo; citarlo nei crediti |
|
| `pieve-interno.png` | Codex | `pieve-interno.png` | Mariano Mirannalti (mandata ad Andrea su WhatsApp) | sì, se Mariano è d'accordo; citarlo nei crediti |
|
||||||
| `panorama-intro.png` | Codex | `altre/panorama-intro.png` | da internet (screenshot con l'icona di Google Lens) | **no**, finché non si sostituisce |
|
| `panorama-intro.png` | Codex | `altre/panorama-intro.png` | da internet (screenshot con l'icona di Google Lens) | **no**, finché non si sostituisce |
|
||||||
|
|||||||
@@ -18,6 +18,22 @@ Online su 50037.manzolo.it tutto fino agli effetti ambientali di Codex. Aperto,
|
|||||||
|
|
||||||
## Dove siamo arrivati
|
## Dove siamo arrivati
|
||||||
|
|
||||||
|
- **Nuovi posti dalle foto di Andrea (29 ottobre, sfondi di Codex)**: Via della Compagnia (fra Via de' Medici, la
|
||||||
|
Pieve e Villa Adami), Via Cafaggio in tre tratti fino alla rotonda, la Provinciale sotto i platani, la passeggiata
|
||||||
|
sulla Carza (cascatella, orti, dietro le poste, sotto il ponte delle poste, gli orti dello zio Mario), la strada fra
|
||||||
|
il bivio della Provinciale e la stazione. Le strade vecchie passano ora da questi posti. Battute provvisorie
|
||||||
|
[DA ANDREA]; foto originali in `assets/raw/foto/`.
|
||||||
|
- **La cerbottana (29 ottobre)**: in piazza, la bottega di Pierin di Frilli sotto la tenda rossa; si compra lo stucco
|
||||||
|
verde e si tira al muro della piazza (`muro-cerbottana.png`, Codex). Motore `cerbottana.js`, disegno
|
||||||
|
`cerbottana-render.js`: si mira, si tiene premuto per il fiato (giusto al 70%: poco cade sotto, troppo va sopra), il
|
||||||
|
mirino ondeggia col respiro, troppo a fiato pieno si tossisce. Bersaglio di gesso (10/5/2), lattine sul muretto
|
||||||
|
(3), barattolo appeso (8, seria e a fassi male); 12 pallini, servono 30/40/50 punti; i pallini restano sul muro.
|
||||||
|
Test in `cerbottana.test.mjs` e `npm run browser:cerbottana`. [DA ANDREA] le battute, com'era la bottega, se far
|
||||||
|
comparire Pierino (è scomparso da anni: decide Andrea).
|
||||||
|
- **Il terrazzo di casa a Cardetole (29 ottobre)**: dalla foto di Andrea dalla finestra (il paese che sale e lassù
|
||||||
|
la Fortezza), Codex l'ha dipinta e ci ha messo davanti il terrazzo (`terrazza-cardetole.png`). Ci si sale da
|
||||||
|
«casa di Andrea» a Cardetole; la battuta dell'apparecchiare ora è sulla porta-finestra. Battute provvisorie
|
||||||
|
[DA ANDREA]. Come Cardetole, dice dove abita Andrea: da decidere prima di Pages.
|
||||||
- **La Ghiacciomobile nel muro (29 ottobre)**: non è più al circolino di Campomigliaio. In Via Liguri Magelli, prima
|
- **La Ghiacciomobile nel muro (29 ottobre)**: non è più al circolino di Campomigliaio. In Via Liguri Magelli, prima
|
||||||
del tramonto (`!indizio_regolo`), è schiantata dentro il muro giallo coi mattoni rotti e senza targa
|
del tramonto (`!indizio_regolo`), è schiantata dentro il muro giallo coi mattoni rotti e senza targa
|
||||||
(`via-liguri-magelli-muro.png`, ritocco di Codex); dal tramonto il muro è rifatto e c'è la targa. Il motore ha le
|
(`via-liguri-magelli-muro.png`, ritocco di Codex); dal tramonto il muro è rifatto e c'è la targa. Il motore ha le
|
||||||
|
|||||||
@@ -255,6 +255,15 @@
|
|||||||
il pulsante alterna Recupera e Molla. Sei lanci. La gloria: 2 pesci alla bona, 3 seria, 4 a fassi male (lo stivale
|
il pulsante alterna Recupera e Molla. Sei lanci. La gloria: 2 pesci alla bona, 3 seria, 4 a fassi male (lo stivale
|
||||||
non conta, e non pesa). Frecce ← →: distanza del lancio; Esc esce.</p>
|
non conta, e non pesa). Frecce ← →: distanza del lancio; Esc esce.</p>
|
||||||
</details>
|
</details>
|
||||||
|
<details id="cerbottana-help" hidden><summary>Come si gioca</summary>
|
||||||
|
<p>La cerbottana, con lo stucco verde di Pierin di Frilli: dodici pallini contro il muro della piazza. Il bersaglio
|
||||||
|
di gesso vale 10, 5 o 2 punti secondo il cerchio, ogni lattina sul muretto 3, il barattolo appeso che dondola (Seria
|
||||||
|
e A fassi male) 8. Servono 30 punti alla bona, 40 Seria, 50 A fassi male. I pallini restano attaccati al muro.</p>
|
||||||
|
<p>Muovi il mouse o tocca il muro per mirare: il mirino ondeggia col respiro (di più salendo di livello). Tieni
|
||||||
|
premuto per prendere fiato e lascia per sparare: col fiato giusto il pallino va dove punti, con poco cade sotto,
|
||||||
|
con troppo va sopra. Alla bona la barra del fiato segna il punto giusto. Se resti troppo a fiato pieno tossisci, e
|
||||||
|
il pallino è perso. Si può anche regolare il fiato col cursore e premere Spara. Frecce per spostare il mirino.</p>
|
||||||
|
</details>
|
||||||
<details id="micro-help" hidden><summary>Come si gioca</summary>
|
<details id="micro-help" hidden><summary>Come si gioca</summary>
|
||||||
<p>La pista col gesso sul parcheggio di Cardetole: un giro contro il Chiaru, una spinta a testa (prima tu, poi
|
<p>La pista col gesso sul parcheggio di Cardetole: un giro contro il Chiaru, una spinta a testa (prima tu, poi
|
||||||
lui). La tua macchinina è la rossa. Vince chi taglia per primo il traguardo a scacchi; se ci arrivate tutti e due
|
lui). La tua macchinina è la rossa. Vince chi taglia per primo il traguardo a scacchi; se ci arrivate tutti e due
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "leggenda-del-regolo",
|
"name": "leggenda-del-regolo",
|
||||||
"version": "0.1.46",
|
"version": "0.1.48",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
@@ -9,6 +9,7 @@
|
|||||||
"browser:biliardo": "node tests/biliardo.browser.mjs",
|
"browser:biliardo": "node tests/biliardo.browser.mjs",
|
||||||
"browser:micro": "node tests/micro.browser.mjs",
|
"browser:micro": "node tests/micro.browser.mjs",
|
||||||
"browser:gara": "node tests/gara.browser.mjs",
|
"browser:gara": "node tests/gara.browser.mjs",
|
||||||
|
"browser:cerbottana": "node tests/cerbottana.browser.mjs",
|
||||||
"browser:tressette": "node tests/tressette.browser.mjs",
|
"browser:tressette": "node tests/tressette.browser.mjs",
|
||||||
"browser:scopa": "node tests/scopa.browser.mjs",
|
"browser:scopa": "node tests/scopa.browser.mjs",
|
||||||
"browser:briscola": "node tests/briscola.browser.mjs",
|
"browser:briscola": "node tests/briscola.browser.mjs",
|
||||||
|
|||||||
@@ -0,0 +1,102 @@
|
|||||||
|
import { TARGET, CAN, SWINGER, LEDGE, PELLETS, FLIGHT, BEST, rings, reticle, swinger, canThrow, overHeld } from './cerbottana.js';
|
||||||
|
import { text, panel } from './bocce-render.js';
|
||||||
|
|
||||||
|
// Il gesso sul muro: tre cerchi un po' storti (sempre gli stessi) e i numeri dei punti, in alto, ognuno nel suo anello.
|
||||||
|
function chalkTarget(ctx, c) {
|
||||||
|
let inner = 0;
|
||||||
|
for (const [r, p] of rings(c)) {
|
||||||
|
ctx.strokeStyle = 'rgba(250,248,236,0.85)'; ctx.lineWidth = 1.5; ctx.beginPath();
|
||||||
|
for (let k = 0; k <= 48; k++) {
|
||||||
|
const a = k / 48 * Math.PI * 2, j = 0.6 * Math.sin(k * 2.3 + r);
|
||||||
|
const x = TARGET.x + Math.cos(a) * (r + j), y = TARGET.y + Math.sin(a) * (r + j);
|
||||||
|
if (k) ctx.lineTo(x, y); else ctx.moveTo(x, y);
|
||||||
|
}
|
||||||
|
ctx.stroke();
|
||||||
|
if (inner) text(ctx, String(p), TARGET.x, TARGET.y - (inner + r) / 2, 6, 'rgba(250,248,236,0.8)', 'center');
|
||||||
|
inner = r;
|
||||||
|
}
|
||||||
|
ctx.fillStyle = 'rgba(250,248,236,0.9)'; ctx.fillRect(TARGET.x - 1, TARGET.y - 1, 2, 2);
|
||||||
|
}
|
||||||
|
// Una lattina: rossa con la fascia chiara, i bordi d'alluminio.
|
||||||
|
function can(ctx, x, y, angle = 0, color = '#c8321e') {
|
||||||
|
ctx.save(); ctx.translate(Math.round(x), Math.round(y)); ctx.rotate(angle);
|
||||||
|
ctx.fillStyle = 'rgba(20,16,10,0.35)'; ctx.fillRect(-CAN.w / 2 + 2, -1, CAN.w, 2);
|
||||||
|
ctx.fillStyle = color; ctx.fillRect(-CAN.w / 2, -CAN.h, CAN.w, CAN.h);
|
||||||
|
ctx.fillStyle = '#f2e6c8'; ctx.fillRect(-CAN.w / 2, -CAN.h + 6, CAN.w, 4);
|
||||||
|
ctx.fillStyle = '#c9cdd2'; ctx.fillRect(-CAN.w / 2, -CAN.h, CAN.w, 2); ctx.fillRect(-CAN.w / 2, -2, CAN.w, 2);
|
||||||
|
ctx.fillStyle = 'rgba(255,255,255,0.35)'; ctx.fillRect(-CAN.w / 2 + 2, -CAN.h + 2, 1, CAN.h - 4);
|
||||||
|
ctx.restore();
|
||||||
|
}
|
||||||
|
// Un pallino di stucco: verdastro, un po' schiacciato sul muro.
|
||||||
|
function pellet(ctx, x, y, r = 2.5) {
|
||||||
|
ctx.fillStyle = '#2b3a1c'; ctx.beginPath(); ctx.arc(x, y, r + 0.8, 0, Math.PI * 2); ctx.fill();
|
||||||
|
ctx.fillStyle = '#8fa05a'; ctx.beginPath(); ctx.arc(x, y, r, 0, Math.PI * 2); ctx.fill();
|
||||||
|
ctx.fillStyle = '#c3cf8e'; ctx.fillRect(Math.round(x - r / 2), Math.round(y - r / 2), 1, 1);
|
||||||
|
}
|
||||||
|
// La cerbottana in basso, in prospettiva: grossa vicino alla bocca, più fine in punta, girata verso il mirino, col
|
||||||
|
// pallino di stucco in punta.
|
||||||
|
function blowpipe(ctx, c, to) {
|
||||||
|
const from = { x: 320, y: 376 }, a = Math.atan2(to.y - from.y, to.x - from.x), len = 64;
|
||||||
|
const tip = { x: from.x + Math.cos(a) * len, y: from.y + Math.sin(a) * len }, nx = -Math.sin(a), ny = Math.cos(a);
|
||||||
|
const tube = (w0, w1, color) => {
|
||||||
|
ctx.fillStyle = color; ctx.beginPath();
|
||||||
|
ctx.moveTo(from.x + nx * w0, from.y + ny * w0); ctx.lineTo(tip.x + nx * w1, tip.y + ny * w1);
|
||||||
|
ctx.lineTo(tip.x - nx * w1, tip.y - ny * w1); ctx.lineTo(from.x - nx * w0, from.y - ny * w0); ctx.fill();
|
||||||
|
};
|
||||||
|
tube(9, 4, '#2a2018'); tube(7, 3, '#6b5236');
|
||||||
|
ctx.fillStyle = '#8a6a44'; ctx.fillRect(Math.round(tip.x - 1), Math.round(tip.y - 1), 2, 2);
|
||||||
|
if (canThrow(c)) pellet(ctx, tip.x, tip.y - 1, 3.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function drawCerbottana(ctx, c, def, bg) {
|
||||||
|
ctx.save(); ctx.imageSmoothingEnabled = false;
|
||||||
|
if (bg) ctx.drawImage(bg, 0, 0, 640, 360); else { ctx.fillStyle = '#d9a640'; ctx.fillRect(0, 0, 640, 360); }
|
||||||
|
chalkTarget(ctx, c);
|
||||||
|
for (const p of c.stuck) pellet(ctx, p.x, p.y);
|
||||||
|
// Le lattine sul muretto; colpite, cadono all'indietro.
|
||||||
|
for (const k of c.cans) { if (k.fall < 1) can(ctx, k.x, LEDGE + k.fall * 6, -k.fall * 1.4); }
|
||||||
|
if (c.skill.swinger) {
|
||||||
|
const s = swinger(c);
|
||||||
|
ctx.strokeStyle = '#3a3024'; ctx.lineWidth = 1; ctx.beginPath(); ctx.moveTo(SWINGER.x, SWINGER.y); ctx.lineTo(s.x, s.y); ctx.stroke();
|
||||||
|
can(ctx, s.x, s.y + SWINGER.h, s.a + c.swing.spin * Math.sin(c.visual.time * 30) * 0.6, '#2f6fb0');
|
||||||
|
}
|
||||||
|
// Il pallino in volo: parte grande dalla cerbottana e rimpicciolisce andando verso il muro.
|
||||||
|
if (c.shot) {
|
||||||
|
const k = Math.min(1, c.shot.t / FLIGHT), { from, to } = c.shot;
|
||||||
|
pellet(ctx, from.x + (to.x - from.x) * k, from.y + (to.y - from.y) * k - Math.sin(k * Math.PI) * 18, 6 - 3.5 * k);
|
||||||
|
}
|
||||||
|
const r = reticle(c);
|
||||||
|
if (canThrow(c)) {
|
||||||
|
const over = overHeld(c);
|
||||||
|
ctx.strokeStyle = over ? '#ff6a4a' : '#fff8dc'; ctx.lineWidth = 1;
|
||||||
|
ctx.beginPath(); ctx.arc(r.x, r.y, 7, 0, Math.PI * 2); ctx.stroke();
|
||||||
|
ctx.beginPath(); ctx.moveTo(r.x - 11, r.y); ctx.lineTo(r.x - 3, r.y); ctx.moveTo(r.x + 3, r.y); ctx.lineTo(r.x + 11, r.y);
|
||||||
|
ctx.moveTo(r.x, r.y - 11); ctx.lineTo(r.x, r.y - 3); ctx.moveTo(r.x, r.y + 3); ctx.lineTo(r.x, r.y + 11); ctx.stroke();
|
||||||
|
}
|
||||||
|
blowpipe(ctx, c, r);
|
||||||
|
// Il fiato: una barra in basso a sinistra (alla bona col punto giusto segnato).
|
||||||
|
if (canThrow(c)) {
|
||||||
|
const x = 16, y = 300, h = 50;
|
||||||
|
ctx.fillStyle = '#17160fd0'; ctx.fillRect(x - 3, y - 3, 18, h + 6);
|
||||||
|
ctx.fillStyle = overHeld(c) ? '#ff6a4a' : c.power > BEST + 0.08 ? '#ffd23c' : '#9be07c';
|
||||||
|
const f = Math.round(h * c.power); ctx.fillRect(x, y + h - f, 12, f);
|
||||||
|
if (c.skill.sweet) { ctx.fillStyle = '#fff8dc'; ctx.fillRect(x - 3, Math.round(y + h - h * BEST) - 1, 18, 2); }
|
||||||
|
text(ctx, 'FIATO', x + 6, y - 9, 6, '#efd49e', 'center');
|
||||||
|
}
|
||||||
|
// In alto: punti, pallini rimasti e cosa è successo.
|
||||||
|
ctx.fillStyle = '#17160fe8'; ctx.fillRect(0, 0, 640, 22);
|
||||||
|
text(ctx, 'LA CERBOTTANA', 8, 7, 8, '#efd49e');
|
||||||
|
text(ctx, { bona: 'alla bona', seria: 'seria', male: 'a fassi male' }[c.level], 8, 16, 7, '#d9ccba');
|
||||||
|
text(ctx, `Punti ${c.points} / ${c.skill.goal}`, 260, 11, 9, c.points >= c.skill.goal ? '#b9e5b3' : '#fff0c8', 'center');
|
||||||
|
for (let i = 0; i < PELLETS; i++) pellet(ctx, 430 + i * 15, 11, i < c.left ? 3 : 1.2);
|
||||||
|
const line = overHeld(c) ? 'Lascia, sennò tossisci!' : c.line;
|
||||||
|
if (line) { ctx.fillStyle = '#17160fd0'; ctx.fillRect(170, 24, 300, 14); text(ctx, line, 320, 31, 8, overHeld(c) || /corto|alto|Coff/.test(line) ? '#ffbf9f' : '#9fd0ff', 'center'); }
|
||||||
|
if (c.step === 'result') {
|
||||||
|
const won = c.result.winner === 'player';
|
||||||
|
panel(ctx, 170, 140, 300, 76);
|
||||||
|
text(ctx, won ? 'CENTRATO!' : 'LO STUCCO È FINITO', 320, 160, 12, won ? '#b9e5b3' : '#efd49e', 'center');
|
||||||
|
text(ctx, `${c.result.points} punti, ne servivano ${c.result.goal}`, 320, 182, 8, '#efd49e', 'center');
|
||||||
|
text(ctx, 'Torna in piazza per uscire.', 320, 200, 8, '#d9ccba', 'center');
|
||||||
|
}
|
||||||
|
ctx.restore();
|
||||||
|
}
|
||||||
@@ -0,0 +1,146 @@
|
|||||||
|
// La cerbottana (idea di Andrea, 29 ottobre): da ragazzi in piazza si comprava da Pierin di Frilli lo stucco verde,
|
||||||
|
// dall'odore inconfondibile, lo si metteva intorno alla cerbottana, si facevano i pallini e si «sparava» al muro.
|
||||||
|
// Qui: un muro della piazza visto di fronte, un bersaglio fatto col gesso, le lattine sul muretto e (a seria e a fassi
|
||||||
|
// male) un barattolo appeso che dondola. Si mira, si tiene premuto per prendere fiato e si lascia: con poco fiato il
|
||||||
|
// pallino cade sotto, con troppo va sopra; il mirino ondeggia col respiro, e chi resta troppo a fiato pieno tossisce.
|
||||||
|
// I pallini di stucco restano attaccati al muro. Unità: i pixel del primo piano 640×360.
|
||||||
|
|
||||||
|
export const WALL_BOTTOM = 244; // sotto comincia il muretto: lì il pallino non attacca
|
||||||
|
export const LEDGE = 244; // dove poggiano le lattine
|
||||||
|
export const PELLETS = 12, SWING = 1, TAP = 0.14, COUGH = 0.6, FLIGHT = 0.3, REST = 0.5, BEST = 0.7, DROP = 300;
|
||||||
|
export const TARGET = { x: 320, y: 118, rings: [[8, 10], [18, 5], [30, 2]] };
|
||||||
|
export const CAN = { w: 10, h: 16, points: 3 }, SWINGER = { x: 470, y: 8, length: 92, w: 12, h: 16, points: 8 };
|
||||||
|
// I livelli: quanto ondeggia il mirino (px), quanti punti servono, se c'è il barattolo appeso, se la barra del fiato
|
||||||
|
// mostra il punto giusto, e quanto sono grandi i cerchi del bersaglio.
|
||||||
|
export const LEVELS = {
|
||||||
|
bona: { sway: 3, goal: 30, swinger: false, sweet: true, rings: 1.3 },
|
||||||
|
seria: { sway: 6, goal: 40, swinger: true, sweet: false, rings: 1 },
|
||||||
|
male: { sway: 10, goal: 50, swinger: true, sweet: false, rings: 0.85 },
|
||||||
|
};
|
||||||
|
const clamp = (v, lo, hi) => Math.max(lo, Math.min(hi, v));
|
||||||
|
function random(c) { c.seed = (Math.imul(c.seed, 1664525) + 1013904223) >>> 0; return c.seed / 4294967296; }
|
||||||
|
|
||||||
|
export function newCerbottana(seed = Date.now() >>> 0, def = {}) {
|
||||||
|
const level = LEVELS[def.level] ? def.level : 'seria';
|
||||||
|
return { step: 'aim', t: 0, seed, level, skill: LEVELS[level], aim: { x: TARGET.x, y: TARGET.y }, power: BEST,
|
||||||
|
holding: false, holdTime: 0, charging: false, left: PELLETS, points: 0, events: [], shot: null, stuck: [], line: null,
|
||||||
|
cans: [200, 250, 390, 440].map(x => ({ x, down: false, fall: 0 })), swing: { hits: 0, spin: 0 }, visual: { time: 0 } };
|
||||||
|
}
|
||||||
|
export const canThrow = c => c.step === 'aim' && c.left > 0;
|
||||||
|
export const canAdjust = canThrow;
|
||||||
|
export const powerAt = time => clamp(time / SWING, 0, 1);
|
||||||
|
export const rings = c => TARGET.rings.map(([r, p]) => [r * c.skill.rings, p]);
|
||||||
|
|
||||||
|
// Il respiro: il mirino gira piano intorno al punto voluto (due onde, non si ripete subito); trattenendo il fiato pieno
|
||||||
|
// trema di più.
|
||||||
|
export function sway(c) {
|
||||||
|
const t = c.visual.time, a = c.skill.sway * (1 + (c.overHold ?? 0) * 2);
|
||||||
|
return { x: a * (Math.sin(t * 1.7) + 0.5 * Math.sin(t * 3.1 + 1)), y: a * 0.8 * (Math.sin(t * 1.3 + 2) + 0.5 * Math.sin(t * 2.9)) };
|
||||||
|
}
|
||||||
|
export function reticle(c) { const s = sway(c); return { x: c.aim.x + s.x, y: c.aim.y + s.y }; }
|
||||||
|
// Dove arriva il pallino: dove punta il mirino, più su o più giù secondo il fiato (BEST è il fiato giusto).
|
||||||
|
export const landing = (c, power = c.power) => { const r = reticle(c); return { x: r.x, y: r.y + (BEST - power) * DROP }; };
|
||||||
|
// Il barattolo appeso: un pendolo che dondola sotto la gronda (e gira su sé stesso se colpito).
|
||||||
|
export function swinger(c) {
|
||||||
|
const a = 0.5 * Math.sin(c.visual.time * 1.6);
|
||||||
|
return { x: SWINGER.x + Math.sin(a) * SWINGER.length, y: SWINGER.y + Math.cos(a) * SWINGER.length, a };
|
||||||
|
}
|
||||||
|
|
||||||
|
export function shoot(c) {
|
||||||
|
if (!canThrow(c) || c.holding) return false;
|
||||||
|
return fire(c, c.power);
|
||||||
|
}
|
||||||
|
function fire(c, power, cough = false) {
|
||||||
|
const from = { x: 320, y: 380 }, to = cough ? { x: 300 + random(c) * 40, y: 330 } : landing(c, power);
|
||||||
|
c.left--; c.power = power;
|
||||||
|
c.shot = { from, to, t: 0, cough };
|
||||||
|
c.step = 'flying'; c.line = null;
|
||||||
|
c.events.push({ kind: cough ? 'cerbottana-tosse' : 'cerbottana-pff', power });
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// Arrivato: prima il barattolo appeso, poi le lattine, poi il bersaglio; sul muro il pallino resta attaccato.
|
||||||
|
function land(c) {
|
||||||
|
const { x, y } = c.shot.to;
|
||||||
|
let got = 0, what = null;
|
||||||
|
if (c.shot.cough) what = 'Coff! Il pallino è finito per terra.';
|
||||||
|
if (!what && c.skill.swinger) {
|
||||||
|
const s = swinger(c);
|
||||||
|
if (Math.abs(x - s.x) <= SWINGER.w / 2 + 1 && Math.abs(y - s.y - SWINGER.h / 2) <= SWINGER.h / 2 + 1) {
|
||||||
|
got = SWINGER.points; c.swing.hits++; c.swing.spin = 1; what = `Il barattolo appeso! ${got} punti.`;
|
||||||
|
c.events.push({ kind: 'cerbottana-latta', power: 1 });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!what) {
|
||||||
|
const can = c.cans.find(k => !k.down && Math.abs(x - k.x) <= CAN.w / 2 + 1 && y >= LEDGE - CAN.h - 1 && y <= LEDGE);
|
||||||
|
if (can) { can.down = true; got = CAN.points; what = `Lattina giù! ${got} punti.`; c.events.push({ kind: 'cerbottana-latta', power: 0.8 }); }
|
||||||
|
}
|
||||||
|
if (!what) {
|
||||||
|
if (y < WALL_BOTTOM && y > 4 && x > 4 && x < 636) {
|
||||||
|
c.stuck.push({ x, y });
|
||||||
|
const d = Math.hypot(x - TARGET.x, y - TARGET.y), ring = rings(c).find(([r]) => d <= r);
|
||||||
|
got = ring ? ring[1] : 0;
|
||||||
|
what = got ? `Nel bersaglio: ${got} ${got === 1 ? 'punto' : 'punti'}.` : y < TARGET.y - 40 ? 'Troppo fiato: alto.' : 'Sul muro, fuori dal bersaglio.';
|
||||||
|
c.events.push({ kind: 'cerbottana-muro', power: 0.6 });
|
||||||
|
} else what = 'Poco fiato: il pallino è caduto corto.';
|
||||||
|
}
|
||||||
|
c.points += got; c.line = what;
|
||||||
|
c.shot = null; c.step = 'rest'; c.t = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function update(c, dt) {
|
||||||
|
if (!Number.isFinite(dt) || dt <= 0) return;
|
||||||
|
dt = Math.min(dt, 0.25); c.t += dt; c.visual.time += dt;
|
||||||
|
for (const k of c.cans) if (k.down) k.fall = Math.min(1, k.fall + dt * 3);
|
||||||
|
if (c.swing.spin) c.swing.spin = Math.max(0, c.swing.spin - dt);
|
||||||
|
if (c.holding) {
|
||||||
|
c.holdTime += dt; c.charging = c.holdTime >= TAP;
|
||||||
|
c.power = powerAt(c.holdTime);
|
||||||
|
c.overHold = c.power >= 1 ? (c.overHold ?? 0) + dt : 0;
|
||||||
|
// Troppo a fiato pieno: tosse, e il pallino è perso.
|
||||||
|
if (c.overHold > COUGH) { c.holding = c.charging = false; c.overHold = 0; fire(c, 1, true); }
|
||||||
|
}
|
||||||
|
if (c.step === 'flying') { c.shot.t += dt; if (c.shot.t >= FLIGHT) land(c); }
|
||||||
|
else if (c.step === 'rest' && c.t >= REST) {
|
||||||
|
if (c.left > 0) c.step = 'aim';
|
||||||
|
else { c.step = 'result'; c.result = { winner: c.points >= c.skill.goal ? 'player' : 'cpu', points: c.points, goal: c.skill.goal }; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Comandi: il mirino segue il mouse o il dito; tenere premuto prende fiato, lasciare spara.
|
||||||
|
export function aimScreen(c, [x, y]) {
|
||||||
|
if (!canThrow(c) || c.holding || !Number.isFinite(x) || !Number.isFinite(y)) return false;
|
||||||
|
c.aim = { x: clamp(x, 10, 630), y: clamp(y, 24, 300) }; return true;
|
||||||
|
}
|
||||||
|
export function nudge(c, dir) { if (!canThrow(c) || c.holding) return false; c.aim.x = clamp(c.aim.x + dir * 4, 10, 630); return true; }
|
||||||
|
export function setPower(c, value) { if (!canThrow(c) || c.holding || !Number.isFinite(value)) return false; c.power = clamp(value, 0, 1); return true; }
|
||||||
|
export function key(c, key, down) {
|
||||||
|
const move = { ArrowLeft: [-4, 0], ArrowRight: [4, 0], ArrowUp: [0, -4], ArrowDown: [0, 4] }[key];
|
||||||
|
if (!move) return false;
|
||||||
|
if (down && canThrow(c) && !c.holding) c.aim = { x: clamp(c.aim.x + move[0], 10, 630), y: clamp(c.aim.y + move[1], 24, 300) };
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
export function press(c, pointerId) {
|
||||||
|
if (!canThrow(c) || c.holding) return false;
|
||||||
|
c.pointerId = pointerId; c.holding = true; c.charging = false; c.holdTime = 0; c.previousPower = c.power; c.power = 0; c.overHold = 0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
export function cancel(c, pointerId) {
|
||||||
|
if (pointerId !== undefined && c.pointerId !== pointerId) return false;
|
||||||
|
if (!c.holding) return false;
|
||||||
|
c.holding = c.charging = false; c.power = c.previousPower; c.holdTime = 0; c.overHold = 0; return true;
|
||||||
|
}
|
||||||
|
export function release(c, pointerId) {
|
||||||
|
if (c.pointerId !== pointerId || !c.holding) return false;
|
||||||
|
if (c.holdTime < TAP) return cancel(c, pointerId); // il tocco secco mira soltanto
|
||||||
|
c.holding = c.charging = false; c.overHold = 0;
|
||||||
|
return fire(c, c.power);
|
||||||
|
}
|
||||||
|
// Trattenendo il fiato pieno: il disegno avvisa prima della tosse.
|
||||||
|
export const overHeld = c => c.holding && (c.overHold ?? 0) > 0;
|
||||||
|
|
||||||
|
export function button(c) { return c.step === 'result' ? 'Finita' : c.step === 'aim' ? 'Spara' : 'In volo…'; }
|
||||||
|
export function status(c) {
|
||||||
|
const score = `Punti ${c.points} su ${c.skill.goal}, pallini ${c.left} di ${PELLETS}.`;
|
||||||
|
if (c.step === 'result') return `${c.result.winner === 'player' ? 'Fatto! ' : 'Lo stucco è finito. '}${score}`;
|
||||||
|
return `${score} ${c.line ?? 'Mira, tieni premuto per prendere fiato e lascia.'}`;
|
||||||
|
}
|
||||||