Pulsante «?» (o H) che mostra per qualche secondo cosa si può toccare; mappa che si scorre sul telefono
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017egeN2amL84ErjfgQFtEDn
This commit is contained in:
+2
-1
@@ -14,6 +14,7 @@
|
||||
<div id="corner">
|
||||
<button id="pause-button" hidden title="Pausa (Esc)">Pausa</button>
|
||||
<button id="map-button" hidden title="Mappa (P)">Mappa</button>
|
||||
<button id="spots-button" hidden title="Mostra cosa si può toccare (H)">?</button>
|
||||
</div>
|
||||
<div id="sound">
|
||||
<button id="mute" aria-label="Musica: togli l'audio" title="Musica (M)">♪</button>
|
||||
@@ -43,7 +44,7 @@
|
||||
</section>
|
||||
<section id="map" class="overlay" hidden aria-label="Mappa del paese">
|
||||
<h2>San Piero a Sieve</h2>
|
||||
<div id="map-board"><svg id="map-roads" viewBox="0 0 100 100" preserveAspectRatio="none"></svg></div>
|
||||
<div id="map-scroll"><div id="map-board"><svg id="map-roads" viewBox="0 0 100 100" preserveAspectRatio="none"></svg></div></div>
|
||||
<div class="buttons"><button id="close-map">Chiudi</button></div>
|
||||
</section>
|
||||
<section id="pause" class="overlay" hidden aria-label="Pausa">
|
||||
|
||||
+25
-1
@@ -102,7 +102,7 @@ function drawSprite(ctx, { atlas, img }, frame, x, y, scale, facing, size = 1) {
|
||||
ctx.restore();
|
||||
}
|
||||
|
||||
export function render(ctx, game, { hover } = {}) {
|
||||
export function render(ctx, game, { hover, spots } = {}) {
|
||||
const scene = game.scene, s = game.state, bg = backgrounds.get(scene.background);
|
||||
ctx.imageSmoothingEnabled = false;
|
||||
ctx.clearRect(0, 0, WIDTH, HEIGHT);
|
||||
@@ -119,6 +119,7 @@ export function render(ctx, game, { hover } = {}) {
|
||||
if (sheet) queue.push({ y: p.at[1], draw: () => drawSprite(ctx, sheet, game.personPose(p), ...p.at, game.scaleAt(p.at[1]), p.facing ?? 1, p.size) });
|
||||
}
|
||||
for (const q of queue.sort((a, b) => a.y - b.y)) q.draw();
|
||||
if (spots) drawSpots(ctx, game);
|
||||
if (hover) {
|
||||
ctx.strokeStyle = 'rgba(255,255,255,0.35)';
|
||||
ctx.setLineDash([3, 3]);
|
||||
@@ -126,3 +127,26 @@ export function render(ctx, game, { hover } = {}) {
|
||||
ctx.setLineDash([]);
|
||||
}
|
||||
}
|
||||
|
||||
// Il pulsante «?»: un segno su ogni cosa che si può toccare, col suo nome. Le uscite in giallo, il resto in bianco.
|
||||
function drawSpots(ctx, game) {
|
||||
ctx.save();
|
||||
ctx.font = '6px "Press Start 2P", monospace';
|
||||
ctx.textAlign = 'center';
|
||||
ctx.textBaseline = 'bottom';
|
||||
for (const h of game.hotspots()) {
|
||||
const [x, y, w, hh] = h.box, cx = Math.round(x + w / 2), cy = Math.round(y + hh / 2);
|
||||
const color = h.exit ? '#ffd27a' : '#ffffff';
|
||||
ctx.fillStyle = 'rgba(0,0,0,0.55)';
|
||||
ctx.fillRect(cx - 4, cy - 4, 9, 9);
|
||||
ctx.fillStyle = color;
|
||||
ctx.fillRect(cx - 3, cy - 3, 7, 7);
|
||||
ctx.lineWidth = 3;
|
||||
ctx.strokeStyle = '#000';
|
||||
// Il nome resta dentro la scena anche per le uscite sui bordi.
|
||||
const half = ctx.measureText(h.name).width / 2, tx = Math.max(half + 2, Math.min(WIDTH - half - 2, cx)), ty = Math.max(10, cy - 6);
|
||||
ctx.strokeText(h.name, tx, ty);
|
||||
ctx.fillText(h.name, tx, ty);
|
||||
}
|
||||
ctx.restore();
|
||||
}
|
||||
|
||||
+11
-1
@@ -102,9 +102,17 @@ function openMap() {
|
||||
return b;
|
||||
}));
|
||||
$('map').hidden = false;
|
||||
// Sul telefono la pianta scorre: si parte col posto dove si è, al centro.
|
||||
board.querySelector('.here')?.scrollIntoView({ block: 'center', inline: 'center' });
|
||||
}
|
||||
$('map-button').addEventListener('click', openMap);
|
||||
|
||||
// --- «?»: per qualche secondo si vede tutto quello che si può toccare (sul telefono non c'è il mouse da passarci sopra).
|
||||
const SPOTS_TIME = 3500;
|
||||
let spotsUntil = 0;
|
||||
const showSpots = () => { spotsUntil = performance.now() + SPOTS_TIME; };
|
||||
$('spots-button').addEventListener('click', showSpots);
|
||||
|
||||
// --- Pausa: ferma il gioco; da qui mappa, crediti o ritorno al titolo (la partita resta salvata per «Continua»).
|
||||
function openPause() {
|
||||
if (!running) return;
|
||||
@@ -242,6 +250,7 @@ window.addEventListener('keydown', e => {
|
||||
if (!$('pause').hidden) { if (e.key === 'Escape') closePause(); return; }
|
||||
if (!$('map').hidden) { if (e.key === 'Escape' || e.key === 'p' || e.key === 'P') $('map').hidden = true; return; }
|
||||
if ((e.key === 'p' || e.key === 'P') && running) { openMap(); return; }
|
||||
if ((e.key === 'h' || e.key === 'H') && running) { showSpots(); 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 (!running) return;
|
||||
@@ -280,6 +289,7 @@ function updateUi() {
|
||||
// Il pulsante della mappa c'è solo in partita, fuori dai dialoghi, e quando c'è almeno un altro posto dove andare.
|
||||
$('map-button').hidden = !running || !!game.dialogue || game.mapPlaces().length < 2;
|
||||
$('pause-button').hidden = !running;
|
||||
$('spots-button').hidden = !running;
|
||||
if (game.state.ended && !game.speech && !game.queue.length) {
|
||||
running = false;
|
||||
$('ending').hidden = false;
|
||||
@@ -299,7 +309,7 @@ function frame(now) {
|
||||
if (running && now - idleSince > IDLE_PAUSE && !game.speech && !game.walking && !game.queue.length) openPause();
|
||||
if (game) {
|
||||
if (running) game.update(dt);
|
||||
render(ctx, game, { hover: debug && hoverTarget ? game.hotspot(hoverTarget) : null });
|
||||
render(ctx, game, { hover: debug && hoverTarget ? game.hotspot(hoverTarget) : null, spots: running && now < spotsUntil });
|
||||
updateUi();
|
||||
}
|
||||
requestAnimationFrame(frame);
|
||||
|
||||
@@ -106,18 +106,20 @@ body { display: flex; justify-content: center; overflow-x: hidden; -webkit-tap-h
|
||||
/* Mappa: la pianta del paese a gradini, i posti visti come cartellini, le strade come linee. */
|
||||
/* In alto a sinistra: Pausa e Mappa. */
|
||||
#corner { position: absolute; top: 6px; left: 6px; z-index: 2; display: flex; gap: 6px; }
|
||||
#map-button, #pause-button { font: bold clamp(8.64px, 1.15vw, 11.52px) var(--font); padding: .35em .8em;
|
||||
#map-button, #pause-button, #spots-button { font: bold clamp(8.64px, 1.15vw, 11.52px) var(--font); padding: .35em .8em;
|
||||
color: var(--accent); background: rgba(27, 20, 32, .62); border: 0; border-radius: 18px; cursor: pointer; }
|
||||
#pause { z-index: 3; background: rgba(15, 10, 20, .9); }
|
||||
.pause-buttons { flex-direction: column; align-items: stretch; min-width: min(70%, 16em); }
|
||||
#pause .hint { color: var(--dim); }
|
||||
#map { z-index: 3; justify-content: flex-start; padding-top: 2.5%; background: rgba(15, 10, 20, .94); }
|
||||
#map h2 { font-size: clamp(12.96px, 2.16vw, 23.04px); }
|
||||
#map-board { position: relative; width: 92%; flex: 1; min-height: 0; margin: .3em 0;
|
||||
/* Sui telefoni la pianta resta grande quanto serve per leggerla e si scorre col dito. */
|
||||
#map-scroll { width: 92%; flex: 1; min-height: 0; margin: .3em 0; overflow: auto; -webkit-overflow-scrolling: touch; }
|
||||
#map-board { position: relative; width: 100%; height: 100%; min-width: 900px; min-height: 380px;
|
||||
background: repeating-linear-gradient(transparent 0 calc(25% - 1px), rgba(185, 169, 194, .12) calc(25% - 1px) 25%), radial-gradient(circle at 50% 60%, #3a2d42, #231a29); border-radius: 8px; }
|
||||
#map-roads { position: absolute; inset: 0; width: 100%; height: 100%; }
|
||||
#map-roads line { stroke: #b9a9c2; stroke-width: 2.5; stroke-dasharray: 5 4; vector-effect: non-scaling-stroke; opacity: .7; }
|
||||
#map-board button { position: absolute; transform: translate(-50%, -50%); font: clamp(6px, .82vw, 9px) var(--font); padding: .35em .45em;
|
||||
#map-board button { position: absolute; transform: translate(-50%, -50%); font: 9px var(--font); padding: .35em .45em;
|
||||
color: var(--bg); background: var(--ink); border: 2px solid #000; border-radius: 6px; cursor: pointer; white-space: nowrap; }
|
||||
#map-board button:hover { background: var(--accent); }
|
||||
#map-board button.here { color: var(--ink); background: #2f5fb3; cursor: default; }
|
||||
|
||||
@@ -90,6 +90,9 @@ try {
|
||||
await page.mouse.dblclick(r.x + 300 / 640 * r.width, r.y + 330 / 360 * r.height);
|
||||
assert.ok(await page.evaluate(() => game.hurry), 'il doppio clic fa correre');
|
||||
await settle(page);
|
||||
// «?» mostra per qualche secondo cosa si può toccare.
|
||||
await page.click('#spots-button');
|
||||
await page.screenshot({ path: `${OUT}/02c-punti.png` });
|
||||
// Pausa: Esc o il pulsante fermano il gioco; Riprendi torna dov'eri; il titolo offre «Continua».
|
||||
await page.keyboard.press('Escape');
|
||||
await page.waitForSelector('#pause:not([hidden])');
|
||||
|
||||
Reference in New Issue
Block a user