Crediti dal titolo e dalla fine, con la dedica al Lele in testa; le idee di Yuri e Francesco
I crediti stanno in story.credits (un ruolo, i nomi): Yuri Baldi per idee e consigli, Francesco Bacci per storia e aneddoti di San Piero. In piccolo, la nota che Monkey Island è un marchio di Lucasfilm citato solo nella dedica. In docs/IDEE.md chi ci aiuta, il gioco in due parti con i giochi del paese dopo la storia (Yuri) e il Maestro Bacci. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UdeKd62opy9PKgpQXtVctF
This commit is contained in:
@@ -3,8 +3,29 @@
|
|||||||
Battute, oggetti e scherzi proposti da Andrea, in attesa di un posto nella storia. Quando un'idea entra nel gioco
|
Battute, oggetti e scherzi proposti da Andrea, in attesa di un posto nella storia. Quando un'idea entra nel gioco
|
||||||
si segna qui con la data e il punto di `src/story/story.js` dove sta; le persone vere entrano solo col loro consenso.
|
si segna qui con la data e il punto di `src/story/story.js` dove sta; le persone vere entrano solo col loro consenso.
|
||||||
|
|
||||||
|
## Chi ci aiuta
|
||||||
|
|
||||||
|
- **Yuri Baldi** (dal 2026-10-23): manda idee per sviluppare il gioco; vanno qui sotto, col suo nome. Nei crediti
|
||||||
|
sotto «Idee e consigli».
|
||||||
|
- **Francesco Bacci** (dal 2026-10-23): vuole aiutare con la storia vera di San Piero e con gli aneddoti del paese.
|
||||||
|
Suo nonno era il Maestro Bacci. Nei crediti sotto «Storia e aneddoti di San Piero». I suoi racconti sono la fonte
|
||||||
|
per le parti segnate [DA ANDREA] di `docs/PROGETTO.md`.
|
||||||
|
|
||||||
## In attesa
|
## In attesa
|
||||||
|
|
||||||
|
- **Il gioco in due parti** (Yuri Baldi, 2026-10-23). Prima la storia, l'avventura che stiamo facendo; finita
|
||||||
|
quella, si aprono i giochi del paese, uno per uno:
|
||||||
|
- il gioco del Regolo;
|
||||||
|
- il gioco del Palio;
|
||||||
|
- le ragazze col gioco delle bandierine;
|
||||||
|
- la caccia al tesoro per il paese;
|
||||||
|
- le carrette che portano i mattoni su in Fortezza;
|
||||||
|
- il passamano dei mattoni.
|
||||||
|
Va d'accordo con `docs/PROGETTO.md` (le sfide del Palietto: passamano, carretta, vaglio della rena): da decidere
|
||||||
|
se le sfide restano dentro la storia, diventano giochi a parte dopo il finale, o tutte e due le cose.
|
||||||
|
- **Il Maestro Bacci** (Francesco Bacci, 2026-10-23): il nonno di Francesco. Se e come farlo comparire (un
|
||||||
|
personaggio, una citazione, un luogo) lo decidono Andrea e Francesco.
|
||||||
|
|
||||||
- **Oratorio, la pastasciutta di Mariano** (2026-10-23). Alle tavolate dell'oratorio Andrea dice che se aspetta che
|
- **Oratorio, la pastasciutta di Mariano** (2026-10-23). Alle tavolate dell'oratorio Andrea dice che se aspetta che
|
||||||
Mariano gli porti un piatto di pasta, addio: Mariano è sempre a Novoli. Andrebbe in «Usa tavolate» al posto
|
Mariano gli porti un piatto di pasta, addio: Mariano è sempre a Novoli. Andrebbe in «Usa tavolate» al posto
|
||||||
della battuta provvisoria sulla pastasciutta. Prima: il consenso di Mariano a comparire col suo nome.
|
della battuta provvisoria sulla pastasciutta. Prima: il consenso di Mariano a comparire col suo nome.
|
||||||
|
|||||||
+9
-2
@@ -23,7 +23,7 @@
|
|||||||
<section id="title" class="overlay" hidden>
|
<section id="title" class="overlay" hidden>
|
||||||
<h1>La Leggenda<br>del <span>Regolo</span></h1>
|
<h1>La Leggenda<br>del <span>Regolo</span></h1>
|
||||||
<p class="subtitle">San Piero a Sieve · Palio della Fortezza · 2007</p>
|
<p class="subtitle">San Piero a Sieve · Palio della Fortezza · 2007</p>
|
||||||
<div class="buttons"><button id="continue" hidden>Continua</button><button id="new-game">Nuova partita</button></div>
|
<div class="buttons"><button id="continue" hidden>Continua</button><button id="new-game">Nuova partita</button><button class="open-credits secondary">Crediti</button></div>
|
||||||
<p class="dedication">Al Lele, che mi ha fatto conoscere Monkey Island.</p>
|
<p class="dedication">Al Lele, che mi ha fatto conoscere Monkey Island.</p>
|
||||||
</section>
|
</section>
|
||||||
<section id="intro" class="overlay" hidden>
|
<section id="intro" class="overlay" hidden>
|
||||||
@@ -35,7 +35,14 @@
|
|||||||
<h2>Fine del prototipo</h2>
|
<h2>Fine del prototipo</h2>
|
||||||
<p>Il Regolo è passato di qui. Il resto della storia è ancora da scrivere.</p>
|
<p>Il Regolo è passato di qui. Il resto della storia è ancora da scrivere.</p>
|
||||||
<p class="dedication">Al Lele, che mi ha fatto conoscere Monkey Island.</p>
|
<p class="dedication">Al Lele, che mi ha fatto conoscere Monkey Island.</p>
|
||||||
<div class="buttons"><button id="restart">Ricomincia</button></div>
|
<div class="buttons"><button id="restart">Ricomincia</button><button class="open-credits secondary">Crediti</button></div>
|
||||||
|
</section>
|
||||||
|
<section id="credits" class="overlay" hidden aria-label="Crediti">
|
||||||
|
<h2>Crediti</h2>
|
||||||
|
<p class="dedication credits-dedication">Al Lele, che mi ha fatto conoscere Monkey Island.</p>
|
||||||
|
<dl id="credits-list"></dl>
|
||||||
|
<p class="legal">Monkey Island è un marchio di Lucasfilm Ltd., citato solo nella dedica: questo gioco non è affiliato né approvato da Lucasfilm.</p>
|
||||||
|
<div class="buttons"><button id="close-credits">Chiudi</button></div>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
<div id="side">
|
<div id="side">
|
||||||
|
|||||||
+11
@@ -68,6 +68,16 @@ function nextIntro() {
|
|||||||
$('intro').addEventListener('click', e => { if (e.target !== $('skip-intro')) nextIntro(); });
|
$('intro').addEventListener('click', e => { if (e.target !== $('skip-intro')) nextIntro(); });
|
||||||
$('skip-intro').addEventListener('click', () => { introLine = story.intro.length; nextIntro(); });
|
$('skip-intro').addEventListener('click', () => { introLine = story.intro.length; nextIntro(); });
|
||||||
|
|
||||||
|
// --- Crediti: costruiti da story.credits; si aprono dal titolo e dalla fine, Chiudi o Esc tornano indietro.
|
||||||
|
$('credits-list').replaceChildren(...(story.credits ?? []).flatMap(({ role, names }) => {
|
||||||
|
const dt = document.createElement('dt'), dd = document.createElement('dd');
|
||||||
|
dt.textContent = role;
|
||||||
|
dd.textContent = names.join(' · ');
|
||||||
|
return [dt, dd];
|
||||||
|
}));
|
||||||
|
for (const b of document.querySelectorAll('.open-credits')) b.addEventListener('click', () => { $('credits').hidden = false; });
|
||||||
|
$('close-credits').addEventListener('click', () => { $('credits').hidden = true; });
|
||||||
|
|
||||||
function showTitle() {
|
function showTitle() {
|
||||||
running = false;
|
running = false;
|
||||||
const saved = storage && readSave(storage);
|
const saved = storage && readSave(storage);
|
||||||
@@ -159,6 +169,7 @@ function updateChoices() {
|
|||||||
|
|
||||||
window.addEventListener('keydown', e => {
|
window.addEventListener('keydown', e => {
|
||||||
if (e.target === $('volume')) return;
|
if (e.target === $('volume')) return;
|
||||||
|
if (!$('credits').hidden) { if (e.key === 'Escape') $('credits').hidden = true; return; }
|
||||||
if (!$('intro').hidden && [' ', 'Enter'].includes(e.key)) { e.preventDefault(); nextIntro(); return; }
|
if (!$('intro').hidden && [' ', 'Enter'].includes(e.key)) { e.preventDefault(); nextIntro(); return; }
|
||||||
if (e.key === 'm' || e.key === 'M') { music.toggle(); saveAudio(); showSound(); return; }
|
if (e.key === 'm' || e.key === 'M') { music.toggle(); saveAudio(); showSound(); return; }
|
||||||
if (!running) return;
|
if (!running) return;
|
||||||
|
|||||||
@@ -15,6 +15,16 @@ export const story = {
|
|||||||
// Colonna sonora di Andrea (fatta con Suno): titolo, paese, ricordi (fine e Trebbio).
|
// Colonna sonora di Andrea (fatta con Suno): titolo, paese, ricordi (fine e Trebbio).
|
||||||
// splash: la musichetta del cartello d'apertura (tools/jingle.py), suonata una volta sola.
|
// splash: la musichetta del cartello d'apertura (tools/jingle.py), suonata una volta sola.
|
||||||
music: { splash: 'assets/audio/cartello.mp3', title: 'assets/audio/titolo.mp3', game: 'assets/audio/paese.mp3', ending: 'assets/audio/ricordi.mp3' },
|
music: { splash: 'assets/audio/cartello.mp3', title: 'assets/audio/titolo.mp3', game: 'assets/audio/paese.mp3', ending: 'assets/audio/ricordi.mp3' },
|
||||||
|
// I crediti, schermata «Crediti» dal titolo e dalla fine: un ruolo e chi l'ha fatto. Arriveranno man mano.
|
||||||
|
credits: [
|
||||||
|
{ role: 'Un gioco di', names: ['Andrea Manzi «Manzolo»'] },
|
||||||
|
{ role: 'Idee e consigli', names: ['Yuri Baldi'] },
|
||||||
|
{ role: 'Storia e aneddoti di San Piero', names: ['Francesco Bacci'] },
|
||||||
|
{ role: 'Musica', names: ['Andrea Manzi, con Suno'] },
|
||||||
|
{ role: 'Sfondi', names: ['dalle fotografie di San Piero di Andrea'] },
|
||||||
|
{ role: 'Voci', names: ['XTTS-v2 di Coqui'] },
|
||||||
|
{ role: 'Programmazione', names: ['Andrea Manzi, con Claude'] },
|
||||||
|
],
|
||||||
characters: {
|
characters: {
|
||||||
andrea: { name: 'Andrea', color: '#ffffff', sprite: 'assets/characters/andrea.json' },
|
andrea: { name: 'Andrea', color: '#ffffff', sprite: 'assets/characters/andrea.json' },
|
||||||
vecchietta: { name: 'Vecchietta', color: '#ffd27a', sprite: 'assets/characters/vecchietta.json' },
|
vecchietta: { name: 'Vecchietta', color: '#ffd27a', sprite: 'assets/characters/vecchietta.json' },
|
||||||
|
|||||||
@@ -93,6 +93,15 @@ body { display: flex; justify-content: center; overflow-x: hidden; -webkit-tap-h
|
|||||||
.buttons button { font: inherit; font-weight: bold; font-size: clamp(15px, 2.2vw, 22px); padding: .45em 1.2em; border-radius: 6px; cursor: pointer;
|
.buttons button { font: inherit; font-weight: bold; font-size: clamp(15px, 2.2vw, 22px); padding: .45em 1.2em; border-radius: 6px; cursor: pointer;
|
||||||
color: var(--bg); background: var(--accent); border: 0; }
|
color: var(--bg); background: var(--accent); border: 0; }
|
||||||
#continue { background: #7fe08a; }
|
#continue { background: #7fe08a; }
|
||||||
|
.buttons button.secondary { color: var(--ink); background: rgba(42, 32, 48, .85); box-shadow: inset 0 0 0 2px var(--dim); }
|
||||||
|
/* Crediti: sopra titolo e fine (z-index), una voce per ruolo; scorrono se non ci stanno. */
|
||||||
|
#credits { z-index: 3; justify-content: flex-start; overflow-y: auto; padding-top: 4%; background: rgba(15, 10, 20, .96); }
|
||||||
|
#credits .credits-dedication { margin: .2em 0 .5em !important; font-size: clamp(16px, 2.6vw, 28px); }
|
||||||
|
/* Due colonne: il ruolo a destra della sua colonna, il nome a sinistra della sua, allineati sulla riga. */
|
||||||
|
#credits dl { margin: .2em 0 0; display: grid; grid-template-columns: 1fr 1fr; column-gap: 1em; row-gap: .45em; align-items: baseline; width: min(100%, 44em); }
|
||||||
|
#credits dt { text-align: right; color: var(--dim); font-size: clamp(10px, 1.4vw, 14px); letter-spacing: .12em; text-transform: uppercase; }
|
||||||
|
#credits dd { margin: 0; text-align: left; color: var(--ink); font-size: clamp(13px, 2vw, 20px); font-weight: bold; }
|
||||||
|
#credits .legal { color: var(--dim); font-size: clamp(10px, 1.2vw, 13px); opacity: .8; }
|
||||||
|
|
||||||
#rotate { display: none; padding: 1em; text-align: center; color: var(--dim); }
|
#rotate { display: none; padding: 1em; text-align: center; color: var(--dim); }
|
||||||
@media (orientation: portrait) and (max-width: 700px) { #rotate { display: block; } }
|
@media (orientation: portrait) and (max-width: 700px) { #rotate { display: block; } }
|
||||||
|
|||||||
@@ -58,6 +58,16 @@ try {
|
|||||||
await page.screenshot({ path: `${OUT}/00b-dissolvenza.png` });
|
await page.screenshot({ path: `${OUT}/00b-dissolvenza.png` });
|
||||||
await page.waitForSelector('#splash', { state: 'hidden', timeout: 3000 });
|
await page.waitForSelector('#splash', { state: 'hidden', timeout: 3000 });
|
||||||
await page.screenshot({ path: `${OUT}/01-titolo.png` });
|
await page.screenshot({ path: `${OUT}/01-titolo.png` });
|
||||||
|
// I crediti dal titolo: si aprono, mostrano i nomi, Esc li chiude.
|
||||||
|
await page.click('#title .open-credits');
|
||||||
|
assert.match(await page.textContent('#credits'), /Crediti\s*Al Lele/, 'la dedica al Lele viene per prima');
|
||||||
|
assert.match(await page.textContent('#credits'), /Yuri Baldi/);
|
||||||
|
assert.match(await page.textContent('#credits'), /Francesco Bacci/);
|
||||||
|
await page.screenshot({ path: `${OUT}/01c-crediti.png` });
|
||||||
|
const fitsCredits = await page.evaluate(() => { const c = document.getElementById('credits'); return c.scrollHeight <= c.clientHeight; });
|
||||||
|
assert.ok(fitsCredits, 'i crediti stanno in una schermata');
|
||||||
|
await page.keyboard.press('Escape');
|
||||||
|
assert.ok(await page.isHidden('#credits'), 'Esc chiude i crediti');
|
||||||
await page.click('#new-game');
|
await page.click('#new-game');
|
||||||
// L'introduzione: una riga per clic, poi comincia la partita.
|
// L'introduzione: una riga per clic, poi comincia la partita.
|
||||||
await page.waitForSelector('#intro:not([hidden])');
|
await page.waitForSelector('#intro:not([hidden])');
|
||||||
@@ -99,6 +109,10 @@ try {
|
|||||||
}
|
}
|
||||||
await page.waitForSelector('#ending:not([hidden])');
|
await page.waitForSelector('#ending:not([hidden])');
|
||||||
await page.screenshot({ path: `${OUT}/06-fine.png` });
|
await page.screenshot({ path: `${OUT}/06-fine.png` });
|
||||||
|
await page.click('#ending .open-credits');
|
||||||
|
assert.ok(await page.isVisible('#credits'), 'crediti anche dalla fine');
|
||||||
|
await page.click('#close-credits');
|
||||||
|
assert.ok(await page.isHidden('#credits'));
|
||||||
const saved = await page.evaluate(() => JSON.parse(localStorage.getItem('leggenda-regolo-save')));
|
const saved = await page.evaluate(() => JSON.parse(localStorage.getItem('leggenda-regolo-save')));
|
||||||
assert.ok(saved.ended && saved.inventory.includes('squama'), 'salvataggio finale');
|
assert.ok(saved.ended && saved.inventory.includes('squama'), 'salvataggio finale');
|
||||||
|
|
||||||
|
|||||||
@@ -76,6 +76,16 @@ test('la storia è coerente: scene, oggetti, dialoghi e punti calpestabili esist
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('i crediti: ogni voce ha un ruolo e almeno un nome', () => {
|
||||||
|
assert.ok(story.credits.length > 0);
|
||||||
|
for (const c of story.credits) {
|
||||||
|
assert.ok(c.role?.trim(), 'ruolo vuoto');
|
||||||
|
assert.ok(c.names?.length && c.names.every(n => n.trim()), `nomi vuoti in ${c.role}`);
|
||||||
|
}
|
||||||
|
const all = story.credits.flatMap(c => c.names);
|
||||||
|
for (const name of ['Yuri Baldi', 'Francesco Bacci']) assert.ok(all.includes(name), `manca ${name}`);
|
||||||
|
});
|
||||||
|
|
||||||
test('la soluzione si percorre tutta dall\'inizio alla fine', () => {
|
test('la soluzione si percorre tutta dall\'inizio alla fine', () => {
|
||||||
const saves = [];
|
const saves = [];
|
||||||
const g = new Game(story, { onSave: s => saves.push(s) });
|
const g = new Game(story, { onSave: s => saves.push(s) });
|
||||||
|
|||||||
Reference in New Issue
Block a user