Cartello, titolo, introduzione e crediti a tutto schermo; inventario che si scorre
- Sul telefono il titolo inquadra il bastione col Regolo; il volume resta raggiungibile sopra. - L'inventario è alto quanto i verbi, si scorre e mostra l'ultimo oggetto preso; la prova nel browser lo riempie con 16 oggetti e controlla che resti dentro lo schermo. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017egeN2amL84ErjfgQFtEDn
This commit is contained in:
@@ -196,6 +196,7 @@ let inventoryKey = '', hoverItem = null;
|
|||||||
function updateInventory() {
|
function updateInventory() {
|
||||||
const key = game.state.inventory.join(',') + '|' + command.item;
|
const key = game.state.inventory.join(',') + '|' + command.item;
|
||||||
if (key === inventoryKey) return;
|
if (key === inventoryKey) return;
|
||||||
|
const grew = game.state.inventory.length > inventoryKey.split('|')[0].split(',').filter(Boolean).length;
|
||||||
inventoryKey = key;
|
inventoryKey = key;
|
||||||
const box = $('inventory');
|
const box = $('inventory');
|
||||||
box.replaceChildren(...game.state.inventory.map(id => {
|
box.replaceChildren(...game.state.inventory.map(id => {
|
||||||
@@ -223,6 +224,8 @@ function updateInventory() {
|
|||||||
b.addEventListener('pointerleave', () => { if (hoverItem === id) hoverItem = null; });
|
b.addEventListener('pointerleave', () => { if (hoverItem === id) hoverItem = null; });
|
||||||
return b;
|
return b;
|
||||||
}));
|
}));
|
||||||
|
// Un oggetto nuovo finisce in fondo: si scorre fin lì, così si vede subito.
|
||||||
|
if (grew) box.scrollTop = box.scrollHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Dialoghi: scelte numerate, anche da tastiera.
|
// --- Dialoghi: scelte numerate, anche da tastiera.
|
||||||
@@ -303,6 +306,7 @@ function frame(now) {
|
|||||||
const dt = Math.max(0, Math.min(0.1, (now - last) / 1000));
|
const dt = Math.max(0, Math.min(0.1, (now - last) / 1000));
|
||||||
last = now;
|
last = now;
|
||||||
const screen = !$('title').hidden ? 'title' : !$('splash').hidden ? 'splash' : !$('intro').hidden ? 'intro' : !$('ending').hidden ? 'ending' : 'game';
|
const screen = !$('title').hidden ? 'title' : !$('splash').hidden ? 'splash' : !$('intro').hidden ? 'intro' : !$('ending').hidden ? 'ending' : 'game';
|
||||||
|
document.body.classList.toggle('full', screen === 'title' || screen === 'splash' || screen === 'intro' || !$('credits').hidden);
|
||||||
music.duck = voices.playing ? 0.45 : 1;
|
music.duck = voices.playing ? 0.45 : 1;
|
||||||
music.update(trackFor(story, { screen, scene: game?.state.scene }), dt);
|
music.update(trackFor(story, { screen, scene: game?.state.scene }), dt);
|
||||||
// Un minuto senza toccare niente, a gioco fermo: pausa da sola.
|
// Un minuto senza toccare niente, a gioco fermo: pausa da sola.
|
||||||
|
|||||||
@@ -47,7 +47,9 @@ body { display: flex; justify-content: center; overflow-x: hidden; -webkit-tap-h
|
|||||||
#verbs button:hover, #inventory button:hover { color: var(--ink); }
|
#verbs button:hover, #inventory button:hover { color: var(--ink); }
|
||||||
#verbs button[aria-pressed="true"] { color: var(--bg); background: var(--accent); border-color: var(--accent); }
|
#verbs button[aria-pressed="true"] { color: var(--bg); background: var(--accent); border-color: var(--accent); }
|
||||||
#inventory { display: grid; grid-template-columns: repeat(3, 1fr); grid-auto-rows: minmax(2.4em, auto); gap: 4px; align-content: start;
|
#inventory { display: grid; grid-template-columns: repeat(3, 1fr); grid-auto-rows: minmax(2.4em, auto); gap: 4px; align-content: start;
|
||||||
min-height: 5.4em; padding: 4px; background: #231a29; border: 2px solid #4b3a55; border-radius: 4px; }
|
min-height: 5.4em; padding: 4px; background: #231a29; border: 2px solid #4b3a55; border-radius: 4px;
|
||||||
|
/* L'inventario non allunga mai il pannello: è alto quanto i verbi, e se gli oggetti sono tanti si scorre. */
|
||||||
|
contain: size; overflow-y: auto; overscroll-behavior: contain; scrollbar-width: thin; scrollbar-color: #6a557a transparent; }
|
||||||
#inventory:empty::before { content: 'Inventario'; grid-column: 1 / -1; align-self: center; text-align: center; color: var(--dim); opacity: .45;
|
#inventory:empty::before { content: 'Inventario'; grid-column: 1 / -1; align-self: center; text-align: center; color: var(--dim); opacity: .45;
|
||||||
font-size: clamp(9.36px, 1.22vw, 13.68px); font-weight: bold; letter-spacing: .08em; }
|
font-size: clamp(9.36px, 1.22vw, 13.68px); font-weight: bold; letter-spacing: .08em; }
|
||||||
#inventory button { display: flex; align-items: center; gap: .35em; justify-content: center; color: var(--ink); }
|
#inventory button { display: flex; align-items: center; gap: .35em; justify-content: center; color: var(--ink); }
|
||||||
@@ -64,7 +66,7 @@ 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: linear-gradient(rgba(20, 12, 30, .55), rgba(20, 12, 30, .05) 45%, rgba(20, 12, 30, .7)), url(assets/scenes/titolo.png) center / cover; }
|
background: linear-gradient(rgba(20, 12, 30, .55), rgba(20, 12, 30, .05) 45%, rgba(20, 12, 30, .7)), url(assets/scenes/titolo.png) 86% center / cover; }
|
||||||
#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; }
|
||||||
#title .subtitle { color: var(--ink); text-shadow: 2px 2px 0 #000; }
|
#title .subtitle { color: var(--ink); text-shadow: 2px 2px 0 #000; }
|
||||||
@@ -72,13 +74,26 @@ body { display: flex; justify-content: center; overflow-x: hidden; -webkit-tap-h
|
|||||||
background: linear-gradient(rgba(20, 12, 30, .6), rgba(20, 12, 30, .1) 55%), url(assets/scenes/panorama-intro.png) center / cover, #2a2030; }
|
background: linear-gradient(rgba(20, 12, 30, .6), rgba(20, 12, 30, .1) 55%), url(assets/scenes/panorama-intro.png) center / cover, #2a2030; }
|
||||||
#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; 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; }
|
||||||
#skip-intro { position: absolute; right: 10px; bottom: 10px; font: bold 10.08px var(--font); padding: .3em .9em; border-radius: 6px; border: 0;
|
#skip-intro { position: absolute; right: 10px; bottom: 10px; font: bold 10.08px var(--font); padding: .3em .9em; border-radius: 6px; border: 0;
|
||||||
color: var(--bg); background: var(--dim); cursor: pointer; }
|
color: var(--bg); background: var(--dim); cursor: pointer; }
|
||||||
@keyframes appear { from { opacity: 0; transform: translateY(6px); } }
|
@keyframes appear { from { opacity: 0; transform: translateY(6px); } }
|
||||||
/* Cartello d'apertura «Manzolo (Poca) Art Presents»: le parole entrano una alla volta, il «(Poca)» cade dall'alto
|
/* Cartello d'apertura «Manzolo (Poca) Art Presents»: le parole entrano una alla volta, il «(Poca)» cade dall'alto
|
||||||
come un'aggiunta a mano; dopo 4,3 s sfuma (il JavaScript lo toglie a 5 s). */
|
come un'aggiunta a mano; dopo 4,3 s sfuma (il JavaScript lo toglie a 5 s). */
|
||||||
#splash { z-index: 3; gap: .15em; cursor: pointer; background: radial-gradient(circle at 50% 45%, #2a2030, #0d0910 70%);
|
/* Cartello, titolo, introduzione e crediti a tutto schermo: sul telefono la scena è piccola e non si leggerebbe niente.
|
||||||
|
Il volume resta raggiungibile sopra di loro. */
|
||||||
|
#splash, #title, #intro { position: fixed; inset: 0; z-index: 10; }
|
||||||
|
#credits { position: fixed; inset: 0; z-index: 12; }
|
||||||
|
body.full #sound { position: fixed; z-index: 13; top: max(8px, env(safe-area-inset-top)); right: 8px; }
|
||||||
|
#title h1 { font-size: clamp(28px, 7vw, 84px); }
|
||||||
|
/* Sotto il controllo del volume, che sta in alto a destra. */
|
||||||
|
#title, #intro { padding-top: max(6%, 56px); }
|
||||||
|
#splash .splash-name { font-size: clamp(30px, 9vw, 88px); }
|
||||||
|
#splash .splash-art { font-size: clamp(20px, 5vw, 50px); }
|
||||||
|
#splash .splash-present { font-size: clamp(12px, 2.6vw, 26px); }
|
||||||
|
#title .subtitle { font-size: clamp(11px, 1.8vw, 20px); }
|
||||||
|
#title .buttons button { font-size: clamp(12px, 2vw, 20px); }
|
||||||
|
#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; }
|
animation: splash-out .7s ease-in 4.3s 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);
|
||||||
@@ -140,6 +155,7 @@ body { display: flex; justify-content: center; overflow-x: hidden; -webkit-tap-h
|
|||||||
@media (max-width: 600px) {
|
@media (max-width: 600px) {
|
||||||
#panel { grid-template-columns: 1fr; gap: 6px; padding: 6px; }
|
#panel { grid-template-columns: 1fr; gap: 6px; padding: 6px; }
|
||||||
#verbs button { font-size: 9px; padding: .7em .1em; }
|
#verbs button { font-size: 9px; padding: .7em .1em; }
|
||||||
|
#inventory { height: 7.6em; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Telefono in orizzontale: la scena prende tutta l'altezza, verbi e inventario vanno di lato. */
|
/* Telefono in orizzontale: la scena prende tutta l'altezza, verbi e inventario vanno di lato. */
|
||||||
@@ -148,8 +164,8 @@ body { display: flex; justify-content: center; overflow-x: hidden; -webkit-tap-h
|
|||||||
#stage { flex: none; width: min(calc(100dvh * 16 / 9), 68vw); align-self: flex-start; }
|
#stage { flex: none; width: min(calc(100dvh * 16 / 9), 68vw); align-self: flex-start; }
|
||||||
#side { flex: 1; min-width: 0; display: flex; flex-direction: column; background: var(--panel); }
|
#side { flex: 1; min-width: 0; display: flex; flex-direction: column; background: var(--panel); }
|
||||||
#sentence { font-size: 10.08px; }
|
#sentence { font-size: 10.08px; }
|
||||||
#panel { grid-template-columns: 1fr; gap: 6px; padding: 6px; }
|
#panel { grid-template-columns: 1fr; grid-template-rows: auto minmax(0, 1fr); flex: 1; min-height: 0; gap: 6px; padding: 6px; }
|
||||||
#inventory { grid-template-columns: repeat(2, 1fr); min-height: 0; }
|
#inventory { grid-template-columns: repeat(2, 1fr); min-height: 0; height: auto; }
|
||||||
#verbs button, #inventory button, #choices li { font-size: 10.08px; }
|
#verbs button, #inventory button, #choices li { font-size: 10.08px; }
|
||||||
/* La colonna di lato è stretta: verbi piccoli che vanno a capo, mai più larghi della colonna (sennò il telefono
|
/* La colonna di lato è stretta: verbi piccoli che vanno a capo, mai più larghi della colonna (sennò il telefono
|
||||||
allarga la pagina e taglia tutto a destra). */
|
allarga la pagina e taglia tutto a destra). */
|
||||||
|
|||||||
@@ -93,6 +93,17 @@ try {
|
|||||||
// «?» mostra per qualche secondo cosa si può toccare.
|
// «?» mostra per qualche secondo cosa si può toccare.
|
||||||
await page.click('#spots-button');
|
await page.click('#spots-button');
|
||||||
await page.screenshot({ path: `${OUT}/02c-punti.png` });
|
await page.screenshot({ path: `${OUT}/02c-punti.png` });
|
||||||
|
// Inventario pieno (16 oggetti di prova): resta alto quanto i verbi, dentro lo schermo, si scorre e mostra l'ultimo preso.
|
||||||
|
await page.evaluate(() => {
|
||||||
|
const items = game.story.items, kinds = ['chiave_oratorio', 'libro', 'squama'];
|
||||||
|
for (let i = 1; i <= 16; i++) { items['prova' + i] = { name: 'prova ' + i, icon: items[kinds[i % 3]].icon }; game.state.inventory.push('prova' + i); }
|
||||||
|
});
|
||||||
|
await page.waitForTimeout(150);
|
||||||
|
const inv = await page.evaluate(() => { const e = document.getElementById('inventory'), r = e.getBoundingClientRect(), last = e.lastElementChild.getBoundingClientRect();
|
||||||
|
return { inside: r.bottom <= innerHeight, scrolls: e.scrollHeight > e.clientHeight, lastVisible: last.bottom <= r.bottom + 1 && last.top >= r.top - 1 }; });
|
||||||
|
assert.deepEqual(inv, { inside: true, scrolls: true, lastVisible: true }, 'inventario pieno');
|
||||||
|
await page.screenshot({ path: `${OUT}/02d-inventario-pieno.png` });
|
||||||
|
await page.evaluate(() => { game.state.inventory = game.state.inventory.filter(i => !i.startsWith('prova')); for (let i = 1; i <= 16; i++) delete game.story.items['prova' + i]; });
|
||||||
// Pausa: Esc o il pulsante fermano il gioco; Riprendi torna dov'eri; il titolo offre «Continua».
|
// Pausa: Esc o il pulsante fermano il gioco; Riprendi torna dov'eri; il titolo offre «Continua».
|
||||||
await page.keyboard.press('Escape');
|
await page.keyboard.press('Escape');
|
||||||
await page.waitForSelector('#pause:not([hidden])');
|
await page.waitForSelector('#pause:not([hidden])');
|
||||||
|
|||||||
Reference in New Issue
Block a user