diff --git a/.gitignore b/.gitignore index 38f3240..1d0ee0e 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,6 @@ prompts/ _site/ __pycache__/ node_modules/ +assets/generated/ +.venv/ +.env diff --git a/Dockerfile b/Dockerfile index d5c144b..9ab4a6c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -6,6 +6,7 @@ COPY index.html style.css /usr/share/nginx/html/ COPY src /usr/share/nginx/html/src COPY assets/scenes /usr/share/nginx/html/assets/scenes COPY assets/characters /usr/share/nginx/html/assets/characters +COPY assets/audio /usr/share/nginx/html/assets/audio EXPOSE 80 HEALTHCHECK --interval=30s --timeout=3s CMD wget -qO- http://127.0.0.1/ >/dev/null || exit 1 diff --git a/Makefile b/Makefile index cd26e94..1509499 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -# LA LEGGENDA DEL REGOLO — comandi di sviluppo, verifica e Docker. +# LA LEGGENDA DEL REGOLO — comandi di sviluppo, verifica, grafica e Docker. # `make` o `make help` elenca i target. SHELL := /bin/bash @@ -6,27 +6,80 @@ SHELL := /bin/bash PORT ?= 8000 DOCKER_PORT ?= 8080 +IMAGE ?= leggenda-regolo +TAG ?= latest COMPOSE ?= DOCKER_PORT=$(DOCKER_PORT) docker compose +PYTHON ?= python3 +NODE ?= node +# Personaggio da ritagliare: make character NAME=andrea (foglio in assets/raw/$(NAME)-sheet.png, 4x2) +NAME ?= andrea +SHEET ?= assets/raw/$(NAME)-sheet.png +HEIGHT ?= 120 +FRAMES ?= walk_1,walk_2,walk_3,walk_4,stand,talk,take,back +REF ?= stand +# Sfondo da preparare: make background SRC=assets/generated/pieve-dalla-salita.png (CROP=x,y,w,h facoltativo) +SRC ?= +DST ?= assets/scenes/$(notdir $(SRC)) +CROP ?= +COLORS ?= 64 -.PHONY: help serve test browser verify up down restart logs ps +.PHONY: help serve open test browser verify sfondi sfondi-genera sfondi-confronto background character \ + build up down restart logs ps shell image-size clean distclean + +## ------------------------------------------------------------ sviluppo help: ## Mostra questo aiuto @echo "LA LEGGENDA DEL REGOLO — target disponibili:"; echo @grep -hE '^[a-zA-Z0-9_-]+:.*?## ' $(MAKEFILE_LIST) | \ - awk 'BEGIN {FS = ":.*?## "}; {printf " \033[36m%-10s\033[0m %s\n", $$1, $$2}' + awk 'BEGIN {FS = ":.*?## "}; {printf " \033[36m%-16s\033[0m %s\n", $$1, $$2}' + @echo; echo "Variabili: PORT=$(PORT) DOCKER_PORT=$(DOCKER_PORT) IMAGE=$(IMAGE):$(TAG)" serve: ## Avvia il server statico locale (PORT=8000) @echo "→ http://localhost:$(PORT)" - python3 -m http.server $(PORT) --bind 0.0.0.0 + $(PYTHON) -m http.server $(PORT) --bind 0.0.0.0 -test: ## Test della logica, della storia e della soluzione completa - node --test tests/*.test.mjs +open: ## Apre il gioco nel browser predefinito (serve già avviato) + @xdg-open "http://localhost:$(PORT)" >/dev/null 2>&1 || open "http://localhost:$(PORT)" + +## ------------------------------------------------------------ verifica + +test: ## Test della logica, della storia, della soluzione completa e del generatore + $(NODE) --test tests/*.test.mjs + $(PYTHON) -m unittest discover -s tests -p "test_*.py" -q browser: ## Partita completa nel browser con Playwright - node tests/browser.mjs + $(NODE) tests/browser.mjs verify: test browser ## Tutti i controlli +## ------------------------------------------------------------ grafica + +sfondi: ## Prova a secco del generatore: quali foto di assets/raw/foto/ genererebbe (nessuna API) + $(PYTHON) tools/genera.py --dry-run + +sfondi-genera: ## Genera davvero gli sfondi con l'API (serve OPENAI_API_KEY; ogni immagine si paga) + @test -n "$$OPENAI_API_KEY" || { echo "manca OPENAI_API_KEY nell'ambiente"; exit 2; } + $(PYTHON) tools/genera.py + +sfondi-confronto: ## Rifà il confronto foto/immagini in assets/generated/index.html e lo apre + $(PYTHON) tools/genera.py --gallery-only + @xdg-open assets/generated/index.html >/dev/null 2>&1 || open assets/generated/index.html + +background: ## Porta uno sfondo a 640x360 nel gioco (SRC=..., DST=..., CROP=x,y,w,h, COLORS=64) + @test -n "$(SRC)" || { echo "uso: make background SRC=assets/generated/nome.png [CROP=x,y,w,h]"; exit 2; } + $(PYTHON) tools/prepare_background.py $(SRC) $(DST) $(if $(CROP),--crop $(CROP)) --colors $(COLORS) + +character: ## Ritaglia un foglio sprite 4x2 e prepara il personaggio (NAME=andrea, SHEET=..., HEIGHT=120, FRAMES=..., REF=stand) + $(PYTHON) tools/slice_sprites.py --sheet $(SHEET) --out /tmp/regolo-$(NAME) --cols 4 --rows 2 \ + --despill --names $(FRAMES) --prefix $(NAME)_ + $(PYTHON) tools/prepare_character.py /tmp/regolo-$(NAME) $(NAME) assets/characters --height $(HEIGHT) \ + --frames $(FRAMES) --ref $(REF) + +## ------------------------------------------------------------ docker + +build: ## Costruisce l'immagine Docker + docker build -t $(IMAGE):$(TAG) . + up: ## Avvia il container (DOCKER_PORT=8080) $(COMPOSE) up -d --build @echo "→ http://localhost:$(DOCKER_PORT)" @@ -41,3 +94,17 @@ logs: ## Segue i log del container ps: ## Stato del container $(COMPOSE) ps + +shell: ## Shell dentro il container + $(COMPOSE) exec leggenda-regolo sh + +image-size: ## Dimensione dell'immagine + @docker image ls $(IMAGE):$(TAG) --format '{{.Repository}}:{{.Tag}} {{.Size}}' + +## ------------------------------------------------------------ pulizia + +clean: ## Rimuove file temporanei + find . -name '__pycache__' -type d -prune -exec rm -rf {} + + +distclean: clean down ## clean + container + immagine Docker + -docker image rm $(IMAGE):$(TAG) diff --git a/README.md b/README.md index 4f3b64e..6d5fd5a 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,17 @@ Il palio, il quadro dipinto dai ragazzi delle medie, è sparito: un ragazzo del Progetto in fase di ideazione: il documento di progetto è in [`docs/PROGETTO.md`](docs/PROGETTO.md). Per ora c'è un prototipo del motore con due scene di prova e grafica provvisoria. +## Generare sfondi dalle fotografie + +Il generatore Python è `tools/genera.py`; istruzioni e prompt delle due nuove vedute +sono descritti in [`docs/GENERAZIONE_SFONDI.md`](docs/GENERAZIONE_SFONDI.md). +Lavora sulle foto di **San Piero a Sieve**, conserva i master a 1536×864 e permette +di prepararne copie a 640×360 per il gioco. + +```zsh +python3 tools/genera.py --dry-run # elenco delle foto, nessuna API e nessun file scritto +``` + ## Giocare in locale ```zsh diff --git a/assets/audio/paese.mp3 b/assets/audio/paese.mp3 new file mode 100644 index 0000000..81763db Binary files /dev/null and b/assets/audio/paese.mp3 differ diff --git a/assets/audio/ricordi.mp3 b/assets/audio/ricordi.mp3 new file mode 100644 index 0000000..f608311 Binary files /dev/null and b/assets/audio/ricordi.mp3 differ diff --git a/assets/audio/titolo.mp3 b/assets/audio/titolo.mp3 new file mode 100644 index 0000000..530ceb6 Binary files /dev/null and b/assets/audio/titolo.mp3 differ diff --git a/assets/characters/andrea.json b/assets/characters/andrea.json index 0b900b8..e95a10b 100644 --- a/assets/characters/andrea.json +++ b/assets/characters/andrea.json @@ -5,66 +5,66 @@ "walk_1": { "x": 0, "y": 0, - "w": 65, + "w": 64, "h": 111, - "ax": 36.6, + "ax": 36.3, "ay": 111 }, "walk_2": { - "x": 67, + "x": 66, "y": 0, - "w": 35, + "w": 34, "h": 111, "ax": 17.8, "ay": 111 }, "walk_3": { - "x": 104, + "x": 102, "y": 0, "w": 64, "h": 111, - "ax": 34.5, + "ax": 34.7, "ay": 111 }, "walk_4": { - "x": 170, + "x": 168, "y": 0, "w": 38, "h": 111, - "ax": 21.5, + "ax": 21.7, "ay": 111 }, "stand": { - "x": 210, + "x": 208, "y": 0, - "w": 34, + "w": 33, "h": 120, - "ax": 15.1, + "ax": 14.9, "ay": 120 }, "talk": { - "x": 246, + "x": 243, "y": 0, - "w": 56, - "h": 121, - "ax": 20.5, - "ay": 121 + "w": 59, + "h": 120, + "ax": 21.6, + "ay": 120 }, "take": { "x": 304, "y": 0, "w": 68, "h": 97, - "ax": 34.7, + "ax": 34.5, "ay": 97 }, "back": { "x": 374, "y": 0, "w": 43, - "h": 120, - "ax": 21.0, - "ay": 120 + "h": 119, + "ax": 20.8, + "ay": 119 } } } diff --git a/assets/characters/andrea.png b/assets/characters/andrea.png index 22bc5a2..aa700b9 100644 Binary files a/assets/characters/andrea.png and b/assets/characters/andrea.png differ diff --git a/assets/characters/vecchietta.json b/assets/characters/vecchietta.json new file mode 100644 index 0000000..1ef5d43 --- /dev/null +++ b/assets/characters/vecchietta.json @@ -0,0 +1,70 @@ +{ + "image": "vecchietta.png", + "height": 96, + "frames": { + "sit": { + "x": 0, + "y": 0, + "w": 52, + "h": 96, + "ax": 20.3, + "ay": 96 + }, + "blink": { + "x": 54, + "y": 0, + "w": 52, + "h": 96, + "ax": 20.1, + "ay": 96 + }, + "talk": { + "x": 108, + "y": 0, + "w": 52, + "h": 96, + "ax": 20.1, + "ay": 96 + }, + "explain": { + "x": 162, + "y": 0, + "w": 56, + "h": 96, + "ax": 23.3, + "ay": 96 + }, + "point": { + "x": 220, + "y": 0, + "w": 63, + "h": 95, + "ax": 28.2, + "ay": 95 + }, + "laugh": { + "x": 285, + "y": 0, + "w": 54, + "h": 95, + "ax": 22.5, + "ay": 95 + }, + "look_down": { + "x": 341, + "y": 0, + "w": 58, + "h": 86, + "ax": 32.9, + "ay": 86 + }, + "arms_crossed": { + "x": 401, + "y": 0, + "w": 52, + "h": 96, + "ax": 16.3, + "ay": 96 + } + } +} diff --git a/assets/characters/vecchietta.png b/assets/characters/vecchietta.png new file mode 100644 index 0000000..a6af6c8 Binary files /dev/null and b/assets/characters/vecchietta.png differ diff --git a/assets/characters/vecchietto.json b/assets/characters/vecchietto.json new file mode 100644 index 0000000..93d5e22 --- /dev/null +++ b/assets/characters/vecchietto.json @@ -0,0 +1,70 @@ +{ + "image": "vecchietto.png", + "height": 96, + "frames": { + "sit": { + "x": 0, + "y": 0, + "w": 76, + "h": 96, + "ax": 31.4, + "ay": 96 + }, + "doze": { + "x": 78, + "y": 0, + "w": 76, + "h": 96, + "ax": 31.5, + "ay": 96 + }, + "talk": { + "x": 156, + "y": 0, + "w": 67, + "h": 96, + "ax": 25.1, + "ay": 96 + }, + "explain": { + "x": 225, + "y": 0, + "w": 62, + "h": 96, + "ax": 27.4, + "ay": 96 + }, + "point": { + "x": 289, + "y": 0, + "w": 74, + "h": 97, + "ax": 31.5, + "ay": 97 + }, + "laugh": { + "x": 365, + "y": 0, + "w": 70, + "h": 97, + "ax": 23.2, + "ay": 97 + }, + "cat": { + "x": 437, + "y": 0, + "w": 67, + "h": 95, + "ax": 24.1, + "ay": 95 + }, + "shrug": { + "x": 506, + "y": 0, + "w": 81, + "h": 97, + "ax": 38.9, + "ay": 97 + } + } +} diff --git a/assets/characters/vecchietto.png b/assets/characters/vecchietto.png new file mode 100644 index 0000000..eaa2210 Binary files /dev/null and b/assets/characters/vecchietto.png differ diff --git a/assets/scenes/bosco-ai-frati.png b/assets/scenes/bosco-ai-frati.png new file mode 100644 index 0000000..bd66e8f Binary files /dev/null and b/assets/scenes/bosco-ai-frati.png differ diff --git a/assets/scenes/campeggio.png b/assets/scenes/campeggio.png new file mode 100644 index 0000000..db64b1c Binary files /dev/null and b/assets/scenes/campeggio.png differ diff --git a/assets/scenes/oratorio.png b/assets/scenes/oratorio.png new file mode 100644 index 0000000..c8a633b Binary files /dev/null and b/assets/scenes/oratorio.png differ diff --git a/assets/scenes/panorama-intro.png b/assets/scenes/panorama-intro.png new file mode 100644 index 0000000..1a1ce04 Binary files /dev/null and b/assets/scenes/panorama-intro.png differ diff --git a/assets/scenes/pieve-dalla-salita.png b/assets/scenes/pieve-dalla-salita.png new file mode 100644 index 0000000..ad69145 Binary files /dev/null and b/assets/scenes/pieve-dalla-salita.png differ diff --git a/assets/scenes/salita-villa-adami.png b/assets/scenes/salita-villa-adami.png new file mode 100644 index 0000000..ca7c422 Binary files /dev/null and b/assets/scenes/salita-villa-adami.png differ diff --git a/assets/scenes/titolo.png b/assets/scenes/titolo.png new file mode 100644 index 0000000..4cd61ae Binary files /dev/null and b/assets/scenes/titolo.png differ diff --git a/assets/scenes/via-de-medici.png b/assets/scenes/via-de-medici.png new file mode 100644 index 0000000..60853e2 Binary files /dev/null and b/assets/scenes/via-de-medici.png differ diff --git a/assets/scenes/viale-cipressi.png b/assets/scenes/viale-cipressi.png new file mode 100644 index 0000000..cb1b1b1 Binary files /dev/null and b/assets/scenes/viale-cipressi.png differ diff --git a/assets/scenes/villa-adami.png b/assets/scenes/villa-adami.png new file mode 100644 index 0000000..a118ed1 Binary files /dev/null and b/assets/scenes/villa-adami.png differ diff --git a/docs/GENERAZIONE_SFONDI.md b/docs/GENERAZIONE_SFONDI.md new file mode 100644 index 0000000..a402d1b --- /dev/null +++ b/docs/GENERAZIONE_SFONDI.md @@ -0,0 +1,168 @@ +# Sfondi dalle foto — La Leggenda del Regolo + +Il prompt iniziale parlava di Calenzano: questo progetto è ambientato a **San +Piero a Sieve, Mugello, fine maggio 2007**. Lo stile è quello delle avventure VGA +del 1993, coerente con `prompts/STILE.md`: pixel nitidi, tavolozza calda limitata, +ambienti vuoti. La prospettiva e l'architettura della fotografia hanno priorità +rispetto alla vecchia indicazione generica «vista laterale come un teatro». + +## Cartelle + +| Percorso | Contenuto | +| --- | --- | +| `assets/raw/foto/` | Foto JPG, JPEG, PNG e WEBP; estensioni anche maiuscole; scansione non ricorsiva | +| `assets/raw/foto/da-fare/` | Oratorio, escluso dal batch per ora | +| `prompts/backgrounds/base.txt` | Stile comune; se assente si usa quello incluso in `tools/genera.py` | +| `prompts/backgrounds/.txt` | Istruzioni della scena, aggiunte allo stile comune | +| `assets/generated/.png` | Risultato 16:9, 1536×864, stesso nome base dell'originale | +| `assets/generated/.responses/` | Risposte originali conservate per riprendere senza ripagare una generazione | +| `assets/generated/registro.json` | Stato, prompt completo, hash foto, modello, tentativi, errori e uso quando disponibile | +| `assets/generated/index.html` | Confronto prima/dopo di tutte le foto in input, anche quelle ancora da generare | +| `assets/scenes/` | Sfondi del gioco a 640×360, preparati separatamente dopo revisione | + +Foto, prompt e risultati intermedi sono esclusi da Git, secondo le convenzioni +del progetto. Per trasferire il lavoro su un altro computer servono anche queste +cartelle locali: il solo repository non include le foto e i prompt specifici. + +## Installazione + +Python 3.10 o successivo: + +```zsh +python3 -m venv .venv +source .venv/bin/activate +python3 -m pip install -r requirements.txt +``` + +Per le chiamate reali il processo deve ricevere `OPENAI_API_KEY` nell'ambiente. +Non salvare la chiave nel codice, nei prompt o in Git. Il programma non carica +file `.env` e non stampa la chiave. In zsh puoi inserirla senza mostrarla o +registrarla nella cronologia: + +```zsh +read -rs 'OPENAI_API_KEY?Chiave OpenAI: ' +export OPENAI_API_KEY +``` + +## Comandi + +Eseguire dalla radice del repository (i percorsi predefiniti sono comunque +relativi allo script, non alla directory da cui lo si lancia): + +```zsh +python3 tools/genera.py --dry-run +python3 tools/genera.py --test --dry-run +python3 tools/genera.py --limit 10 --dry-run +python3 tools/genera.py --gallery-only +``` + +Questi comandi non chiamano l'API. `--dry-run` non scrive nulla e non richiede +SDK o chiave. `--gallery-only` scrive soltanto il confronto HTML. + +Per generare, dopo aver controllato l'elenco: + +```zsh +python3 tools/genera.py --test # prima foto non ancora completata, in ordine alfabetico +python3 tools/genera.py --limit 10 # al massimo dieci foto ancora da completare +python3 tools/genera.py # tutte le foto ancora da completare (ora solo le due nuove vedute) +``` + +Ogni esecuzione reale mostra il conteggio, il modello, la qualità e il massimo +numero di tentativi. Richiede di scrivere **GENERA** prima di contattare OpenAI. +Una risposta vuota, diversa o EOF annulla l'esecuzione. Non esiste conferma +automatica. `--test` genera davvero una foto: per simulare aggiungere `--dry-run`. + +Per usare le cartelle del prompt originale: + +```zsh +python3 tools/genera.py --input-dir originali --output-dir generate --prompt-dir prompt --dry-run +``` + +Opzioni: `--model gpt-image-2`, `--quality high` (anche `low`, `medium`, `auto`), +`--timeout 180` secondi, `--attempts 3` richieste massime per foto, prima inclusa. +Il batch è sequenziale; non usa il servizio Batch API. `--test` e `--limit` sono +alternativi. Foto con uguale nome base, anche con estensioni diverse, causano un +errore preventivo per evitare collisioni sui PNG. + +## API e recupero errori + +Usa l'OpenAI Python SDK e `client.images.edit`, modello predefinito +`gpt-image-2`, `size="1536x864"`, `output_format="png"`, `n=1`. +Questo formato è previsto dalla [documentazione ufficiale di Images Edit](https://developers.openai.com/api/reference/resources/images/methods/edit). +Non viene passato `input_fidelity`: per questo modello gli input hanno già alta +fedeltà, come indicato nella [guida ufficiale](https://developers.openai.com/api/docs/guides/image-prompting). +Nessun cambio automatico di modello in caso di errore. + +Pillow applica l'orientamento EXIF e converte la foto in PNG per l'invio, senza +modificare l'originale. Il risultato viene controllato e, solo se già in 16:9, +normalizzato a 1536×864 con nearest-neighbor. Risposte con proporzioni diverse +restano nella cache per revisione: non vengono stirate o ritagliate di nascosto. + +Timeout, errori di connessione, 408, 409, 429 e 5xx vengono ritentati con attesa +esponenziale limitata; gli altri errori HTTP non vengono ritentati. I retry +automatici dell'SDK sono disattivati per rispettare il numero richiesto. +**Un timeout può verificarsi dopo che il server ha elaborato l'immagine: riprovare +può comportare un altro addebito.** Non viene inventata una stima in euro; +il costo dipende da input, output, qualità e tariffa del modello. + +I PNG esistenti vengono saltati anche senza registro. Prima di chiamare l'API +vengono verificati: se sono corrotti o di formato diverso, il programma si ferma +senza sovrascriverli. Una modifica al prompt non rigenera immagini completate: +per una variante usare un'altra `--output-dir`. Se manca il risultato finale ma +esiste una risposta nella cache, la finalizzazione riparte da quella senza API. +Non avviare due processi sulla stessa cartella di output contemporaneamente. + +Il registro si aggiorna prima di ogni tentativo e dopo ogni foto, tramite +sostituzione atomica. Gli errori SDK sono registrati per tipo/codice, senza +corpo della risposta o intestazioni. Un errore su una foto non blocca le altre; +l'uscita è 1 se ci sono errori, 130 se si interrompe con Ctrl-C. + +## Le due scene preparate + +1. **`pieve-dalla-salita`**: la Pieve vista tornando con lo sguardo verso il basso + dalla salita. Conservare facciata, campanile, canonica, statua, cancello, + parapetti e pendenza. Togliere persone, auto e allestimenti temporanei della + cena. Villa Adami e Fortezza sono più su, dietro la camera: non inserirle + artificialmente nell'immagine. +2. **`salita-villa-adami`**: casa ocra, persiane, leone di terracotta, ringhiera, + muro di sostegno e bivio. Conservare la strada bassa a sinistra e la salita a + destra che curva lungo il muro. La foto verticale richiede estensione + laterale: le parti non fotografate saranno una ricostruzione da controllare. + Rimuovere le auto, lasciare leggibile il bivio. La Fortezza non è visibile + nella foto e non va inventata sullo sfondo. + +L'oratorio resta per dopo. Il percorso indicato da Andrea è **Pieve → Villa +Adami → salita → Fortezza**. Questo materiale documenta la geografia corretta; +il prototipo conserva per ora i suoi collegamenti di prova. + +Le prime due immagini sono state generate il 23 ottobre 2026 **con lo strumento +immagini integrato**, dopo aver completato la preparazione e i test senza rete. +Lo script Python non ha effettuato chiamate API reali. I prompt effettivamente +usati sono salvati nei due file `*.integrated.txt` e nel registro, con +`assets/scenes/piazza-colonna.png` come ulteriore riferimento di stile. +Il modello interno dello strumento non è dichiarato: nel registro non viene +attribuito a `gpt-image-2`. I file restituiti a 1672×941 sono conservati integri +in `.responses/`, con copie normalizzate a 1536×864 e copie per il gioco a +640×360/64 colori. Il generatore li riconosce come completati e li salta. + +## Preparare i file del gioco + +Dopo aver controllato visivamente i master, riusare lo strumento già presente: + +```zsh +python3 tools/prepare_background.py assets/generated/pieve-dalla-salita.png assets/scenes/pieve-dalla-salita.png --colors 64 +python3 tools/prepare_background.py assets/generated/salita-villa-adami.png assets/scenes/salita-villa-adami.png --colors 64 +``` + +Le copie hanno 640×360 pixel e al massimo 64 colori, senza retinatura. Il motore +le ingrandisce senza sfocatura. Gli sfondi non vengono collegati automaticamente +alla storia: vanno definite aree calpestabili e uscite sulla composizione finale. + +## Verifica senza rete + +```zsh +python3 -m unittest discover -s tests -p 'test_genera.py' +``` + +I test usano foto sintetiche e un client simulato: nessuna chiave vera, nessuna +richiesta API, nessun costo. La verifica reale del modello resta distinta. diff --git a/docs/PROGETTO.md b/docs/PROGETTO.md index 5b63539..86ed263 100644 --- a/docs/PROGETTO.md +++ b/docs/PROGETTO.md @@ -84,6 +84,29 @@ notare. Andrea lo convince a restituirlo… e il Regolo, per la prima volta, ass | **Castello del Trebbio** | Il posto della pace e degli aiuti (vedi sotto) | villa-castello medicea, la più antica dei Medici in Mugello | | **Fortezza di San Martino** | Chiusa fino al finale: sotterranei, buio, leggenda | voluta da Cosimo I nel 1569, finita sotto Ferdinando I; nove bastioni, Porta Fiorentina (sud) e Porta Bolognese (nord), un cassero vicino alla porta fiorentina; chiusa dopo il terremoto del 1762, abitata poi dai contadini | +### La mappa: il paese a gradini + +Descritta da Andrea (ottobre 2026). San Piero sale a gradini dalla piazza alla Fortezza: + +``` +Livello 2 Fortezza (fuori dalle mura) ── viale dei cipressi ── Trebbio + │ sale + Salita di Villa Adami (casa col leone di terracotta) ── verso la scuola + │ scende +Livello 1 Villa Adami (villa gialla, persiane verdi, torretta) + ╱ a sinistra: Via de' Medici ╲ a destra +Livello 0 Piazza Colonna ───────────────────── Pieve ── porta della canonica ── Oratorio + │ a diritto │ dietro, a destra: verso il Fiocco di Neve (gelateria) + Ingresso del campeggio ── a destra, sale ── Bosco ai Frati +``` + +- Da Villa Adami, scendendo, la Piazza è a sinistra e la Pieve a destra; Piazza e Pieve sono collegate in basso. +- Dalla Piazza Villa Adami è a sinistra; a diritto si va verso il campeggio e, dopo il campeggio, a destra si sale + verso il **Bosco ai Frati** (scene da fare: Andrea manda le foto). Per ora la strada del campeggio è chiusa con una battuta. +- Dalla salita di Villa Adami una strada scende verso la scuola: per ora è chiusa con una battuta. +- Il Trebbio si vede dal sentiero, lontano in cima al colle boscoso. +- Foto di riferimento in `assets/raw/foto/` (esclusa da git). + ### Il Castello del Trebbio: "lo psicologo" Per Andrea il Trebbio è il posto dove salire a cercare pace (scherzando: il suo psicologo). Nel gioco diventa diff --git a/docs/STATO.md b/docs/STATO.md index 4c8296c..caf9cd7 100644 --- a/docs/STATO.md +++ b/docs/STATO.md @@ -9,8 +9,13 @@ Ultimo aggiornamento: 23 ottobre 2026. Da leggere insieme a `PROGETTO.md` all'in - **Motore** (`src/engine/`): camminata con percorsi su aree concave, profondità, sette verbi + clic intelligente, clic destro / pressione lunga = guarda, inventario con "usa… con" e "dai… a", dialoghi a scelte (anche una tantum), salvataggio automatico con "Continua", fumetti sopra chi parla, impaginazione desktop e telefono. -- **Scene con sfondi veri** (`assets/scenes/`, preparati con `tools/prepare_background.py`): - Piazza Colonna → vicolo → Fortezza (fuori dalle mura) → salita → Castello del Trebbio. +- **Scene con sfondi veri** (`assets/scenes/`), collegate come il paese a gradini (`PROGETTO.md`, «La mappa»): + Piazza Colonna ↔ Pieve (livello 0) → Villa Adami (livello 1) → salita di + Villa Adami con la casa del leone → Fortezza (fuori dalle mura) → sentiero → Castello del Trebbio. +- **Altre scene** (ottobre 2026, dalle foto di Andrea con Codex): Via de' Medici, Oratorio, Ingresso del campeggio, + Bosco ai Frati, viale dei cipressi. Schermata del titolo (Fortezza al tramonto col Regolo) e introduzione a righe sul + panorama del Mugello. +- **Musica** di Andrea (Suno) in `assets/audio/`: titolo e introduzione, paese, ricordi (Trebbio e fine); volume e muto. - **Andrea vero** dal foglio sprite (`assets/characters/`, `tools/slice_sprites.py` + `tools/prepare_character.py`): cammina, parla, si china a prendere, di spalle davanti alle porte. - **Storia di prova** (`src/story/story.js`): il palio è sparito, i vecchietti litigano sulle due leggende, la squama @@ -33,8 +38,33 @@ Ultimo aggiornamento: 23 ottobre 2026. Da leggere insieme a `PROGETTO.md` all'in I prompt fissi (stile, scene, foglio sprite) sono in `prompts/STILE.md`, escluso da git. +### Nuove fotografie e generatore + +- Le tre foto aggiunte in `assets/raw/temp/` sono archiviate senza modifiche in + `assets/raw/foto/`: `pieve-dalla-salita.jpg`, `salita-villa-adami.jpg` e + `da-fare/oratorio-pieve.jpg` (oratorio rimandato). +- Geografia precisata da Andrea: dalla Pieve si sale lasciandola alle spalle, + si sbuca a Villa Adami e si prende la salita verso la Fortezza. La seconda + foto mostra il bivio presso Villa Adami, non le mura della Fortezza. +- `tools/genera.py` prepara batch via Images Edit (`gpt-image-2`), master 1536×864, + prompt in `prompts/backgrounds/`, registro e confronto in `assets/generated/`. + Guida: `docs/GENERAZIONE_SFONDI.md`. Preparazione verificata senza chiamate API, + con test offline e `--dry-run`; la generazione reale richiede conferma. +- Generate le due vedute con lo strumento immagini integrato, dopo la preparazione: + master in `assets/generated/`, copie a 640×360 e 64 colori in + `assets/scenes/pieve-dalla-salita.png` e `assets/scenes/salita-villa-adami.png`. + Prompt effettivi `prompts/backgrounds/*.integrated.txt`; provenienza nel registro. + Da valutare prima di collegarle alla storia e definire camminata e hotspot. + Il percorso API dello script è verificato con un client simulato, non con chiamate reali. + ## Cosa manca +### Prossimi passi +- Vecchietta e vecchietto sono in gioco sulla panchina della Piazza (`assets/characters/`, da + `assets/raw/vecchiett?-sheet.png`): manca il consenso delle persone ritratte prima di pubblicare, e i loro nomi. +- Andrea rifatto dalla sua foto del 2007 (`assets/raw/andrea-sheet-prova-2.png`; il vecchio foglio resta in `andrea-sheet.png`). +- Strada del campeggio (poi Bosco ai Frati) e strada della scuola: per ora battute, scene da fare con le foto di Andrea. + ### Domande per Andrea 1. Cosa c'era dipinto sul palio del 2007? (Un'immagine nuova: quadro ingenuo dei ragazzi delle medie, senza cornice, su sfondo verde.) diff --git a/index.html b/index.html index 2a9afb2..7bb94e3 100644 --- a/index.html +++ b/index.html @@ -11,12 +11,21 @@
+
+ + +

La Leggenda
del Regolo

San Piero a Sieve · Palio della Fortezza · 2007

Al Lele, che mi ha fatto conoscere Monkey Island.

+