Compare commits

...
3 Commits
6 changed files with 29 additions and 10 deletions
+2
View File
@@ -35,6 +35,7 @@
<input id="load-file" type="file" accept=".json,application/json" hidden> <input id="load-file" type="file" accept=".json,application/json" hidden>
<p id="load-error" class="load-error" hidden role="alert"></p> <p id="load-error" class="load-error" hidden role="alert"></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>
<p class="version"></p>
</section> </section>
<section id="rione" class="overlay" hidden aria-label="Scegli il rione"> <section id="rione" class="overlay" hidden aria-label="Scegli il rione">
<h2>Per chi corri quest'anno?</h2> <h2>Per chi corri quest'anno?</h2>
@@ -79,6 +80,7 @@
<button id="to-title" class="secondary">Torna al titolo</button> <button id="to-title" class="secondary">Torna al titolo</button>
</div> </div>
<p class="hint">La partita è salvata: dal titolo si riprende con «Continua». Con «Salva su file» la porti su un altro dispositivo e la apri con «Carica».</p> <p class="hint">La partita è salvata: dal titolo si riprende con «Continua». Con «Salva su file» la porti su un altro dispositivo e la apri con «Carica».</p>
<p class="version"></p>
</section> </section>
<section id="credits" class="overlay" hidden aria-label="Ringraziamenti"> <section id="credits" class="overlay" hidden aria-label="Ringraziamenti">
<h2>Ringraziamenti</h2> <h2>Ringraziamenti</h2>
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "leggenda-del-regolo", "name": "leggenda-del-regolo",
"version": "0.1.0", "version": "0.1.1",
"private": true, "private": true,
"type": "module", "type": "module",
"scripts": { "scripts": {
+5 -4
View File
@@ -6,7 +6,7 @@ import { render, loadAssets, hasBackground, WIDTH, HEIGHT } from './engine/rende
import { readSave, writeSave, clearSave, readAudio, writeAudio, saveFile, saveFileName, readSaveFile } from './engine/storage.js'; import { readSave, writeSave, clearSave, readAudio, writeAudio, saveFile, saveFileName, readSaveFile } from './engine/storage.js';
import { Music, trackFor } from './engine/music.js'; import { Music, trackFor } from './engine/music.js';
import { Voices } from './engine/voices.js'; import { Voices } from './engine/voices.js';
import { versioned } from './version.js'; import { VERSION, versioned } from './version.js';
const $ = id => document.getElementById(id); const $ = id => document.getElementById(id);
const canvas = $('scene'), ctx = canvas.getContext('2d'); const canvas = $('scene'), ctx = canvas.getContext('2d');
@@ -582,12 +582,12 @@ $('restart').addEventListener('click', () => {
// Dietro il titolo si vede già la piazza. // Dietro il titolo si vede già la piazza.
// --- Cartello d'apertura «Manzolo (Poca) Art Presents»: 5 secondi (un clic o un tasto lo salta), poi il titolo. // --- Cartello d'apertura «Manzolo (Poca) Art Presents»: 5 secondi (un clic o un tasto lo salta), poi il titolo.
// Il titolo compare sotto il cartello quando questo comincia a sfumare (style.css, 4,3 s): dissolvenza incrociata, // Il titolo compare sotto il cartello quando questo comincia a sfumare (#splash.out in style.css): dissolvenza
// senza intravedere la piazza nel mezzo. // incrociata, senza intravedere la piazza nel mezzo. I tempi partono da qui, non dal primo disegno della pagina.
const SPLASH_FADE = 4300, SPLASH_END = 5000; const SPLASH_FADE = 4300, SPLASH_END = 5000;
function showSplash() { function showSplash() {
let done = false, revealed = false; let done = false, revealed = false;
const reveal = () => { if (!revealed) { revealed = true; showTitle(); } }; const reveal = () => { if (!revealed) { revealed = true; showTitle(); $('splash').classList.add('out'); } };
const end = () => { const end = () => {
if (done) return; if (done) return;
done = true; done = true;
@@ -608,6 +608,7 @@ function showSplash() {
addEventListener('keydown', end, { once: true }); addEventListener('keydown', end, { once: true });
} }
for (const el of document.querySelectorAll('.version')) el.textContent = `v${VERSION}`;
game = new Game(story); game = new Game(story);
command = new Command(game); command = new Command(game);
showSplash(); showSplash();
+1 -1
View File
@@ -1,5 +1,5 @@
// La versione del gioco: la cambia scripts/bump.sh, insieme a package.json. // La versione del gioco: la cambia scripts/bump.sh, insieme a package.json.
export const VERSION = '0.1.0'; export const VERSION = '0.1.1';
// Immagini, musiche e voci con ?v=<versione>: a ogni versione l'indirizzo cambia e il browser le riscarica, // Immagini, musiche e voci con ?v=<versione>: a ogni versione l'indirizzo cambia e il browser le riscarica,
// mentre fra una versione e l'altra le tiene in cache a lungo (nginx.conf). // mentre fra una versione e l'altra le tiene in cache a lungo (nginx.conf).
+9 -4
View File
@@ -68,12 +68,15 @@ body { display: flex; justify-content: center; overflow-x: hidden; -webkit-tap-h
.overlay[hidden] { display: none; } .overlay[hidden] { display: none; }
/* Titolo e introduzione: le illustrazioni a pixel netti, con una velatura per leggere il testo. */ /* Titolo e introduzione: le illustrazioni a pixel netti, con una velatura per leggere il testo. */
#title { justify-content: flex-start; padding-top: 6%; image-rendering: pixelated; #title { justify-content: flex-start; padding-top: 6%; image-rendering: pixelated;
background: none; } background: #0d0910; } /* fondo pieno: finché l'illustrazione non arriva, sotto non si vede il gioco */
#title .buttons { margin-top: auto; } #title .buttons { margin-top: auto; }
#title .dedication { margin-bottom: 2%; text-shadow: 2px 2px 0 #000; } #title .dedication { margin-bottom: 2%; text-shadow: 2px 2px 0 #000; }
/* La versione (src/version.js), piccola: nell'angolo del titolo e in fondo alla pausa. */
.version { margin: 0; font-size: 9px; color: var(--dim); opacity: .75; }
#title .version { position: absolute; right: 8px; bottom: 6px; text-shadow: 1px 1px 0 #000; }
#title .subtitle { color: var(--ink); text-shadow: 2px 2px 0 #000; } #title .subtitle { color: var(--ink); text-shadow: 2px 2px 0 #000; }
#intro { justify-content: flex-start; padding-top: 7%; cursor: pointer; image-rendering: pixelated; #intro { justify-content: flex-start; padding-top: 7%; cursor: pointer; image-rendering: pixelated;
background: none; } background: #0d0910; } /* fondo pieno: finché l'illustrazione non arriva, sotto non si vede il gioco */
#intro-text { min-height: 4.2em; max-width: 30em; font-size: clamp(11.52px, 1.87vw, 21.6px); font-weight: bold; line-height: 1.3; color: var(--ink); #intro-text { min-height: 4.2em; max-width: 30em; font-size: clamp(11.52px, 1.87vw, 21.6px); font-weight: bold; line-height: 1.3; color: var(--ink);
text-shadow: 2px 0 #000, -2px 0 #000, 0 2px #000, 0 -2px #000; animation: appear .8s ease-out; } text-shadow: 2px 0 #000, -2px 0 #000, 0 2px #000, 0 -2px #000; animation: appear .8s ease-out; }
#intro .hint { margin-top: auto; margin-bottom: 40px; color: var(--dim); font-size: clamp(8.64px, 1.08vw, 11.52px); text-shadow: 1px 1px 0 #000; } #intro .hint { margin-top: auto; margin-bottom: 40px; color: var(--dim); font-size: clamp(8.64px, 1.08vw, 11.52px); text-shadow: 1px 1px 0 #000; }
@@ -110,8 +113,10 @@ body.full #sound { position: fixed; z-index: 13; top: max(8px, env(safe-area-ins
#title .dedication { font-size: max(9px, calc(var(--u) * 1.5)); } #title .dedication { font-size: max(9px, calc(var(--u) * 1.5)); }
#intro-text { font-size: max(11px, calc(var(--u) * 2)); } #intro-text { font-size: max(11px, calc(var(--u) * 2)); }
#title .buttons button { font-size: max(11px, calc(var(--u) * 1.9)); } #title .buttons button { font-size: max(11px, calc(var(--u) * 1.9)); }
#splash { z-index: 11; gap: .15em; cursor: pointer; background: radial-gradient(circle at 50% 45%, #2a2030, #0d0910 70%); #splash { z-index: 11; gap: .15em; cursor: pointer; background: radial-gradient(circle at 50% 45%, #2a2030, #0d0910 70%); }
animation: splash-out .7s ease-in 4.3s forwards; } /* La dissolvenza la avvia main.js insieme al titolo: il CSS arriva prima del codice, e con un orologio suo il cartello
sparirebbe prima che il titolo ci sia. */
#splash.out { animation: splash-out .7s ease-in forwards; }
#splash p { margin: 0; max-width: none; font-weight: bold; text-shadow: 3px 3px 0 #000; opacity: 0; } #splash p { margin: 0; max-width: none; font-weight: bold; text-shadow: 3px 3px 0 #000; opacity: 0; }
#splash .splash-name { font-size: clamp(24.48px, 5.76vw, 63.36px); letter-spacing: .14em; text-transform: uppercase; color: var(--ink); #splash .splash-name { font-size: clamp(24.48px, 5.76vw, 63.36px); letter-spacing: .14em; text-transform: uppercase; color: var(--ink);
animation: splash-in .9s ease-out .2s forwards; } animation: splash-in .9s ease-out .2s forwards; }
+11
View File
@@ -62,6 +62,17 @@ 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` });
assert.match(await page.textContent('#title .version'), /^v\d+\.\d+\.\d+$/, 'la versione nell\'angolo del titolo');
// Col codice lento ad arrivare (rete vera) il cartello aspetta il titolo: non sfuma prima per conto suo.
{
const slow = await browser.newPage({ viewport: { width: 1280, height: 860 } });
await slow.route('**/src/main.js', async route => { await new Promise(r => setTimeout(r, 2000)); await route.continue(); });
await slow.goto(`http://127.0.0.1:${PORT}/`);
await slow.waitForSelector('#title:not([hidden])', { timeout: 12000 });
const opacity = await slow.evaluate(() => Number(getComputedStyle(document.getElementById('splash')).opacity));
assert.ok(opacity > 0.9, `il cartello era già sfumato (${opacity}) quando è comparso il titolo`);
await slow.close();
}
// I crediti dal titolo: si aprono, mostrano i nomi, Esc li chiude. // I crediti dal titolo: si aprono, mostrano i nomi, Esc li chiude.
await page.click('#title .open-credits'); await page.click('#title .open-credits');
assert.match(await page.textContent('#credits'), /Ringraziamenti\s*Al Lele/, 'la dedica al Lele viene per prima'); assert.match(await page.textContent('#credits'), /Ringraziamenti\s*Al Lele/, 'la dedica al Lele viene per prima');