Carte che volano: dalla mano al tavolo e, finita la presa, sul mucchietto di chi ha preso (briscola, tressette, scopa; Andrea: «non si capisce quando vengono buttate le carte»). Il valzer della balera ai tavoli da carte (tools/valzer_carte.py: fisarmonica musette, basso, melodia di mandolino col tremolo), musica per primo piano; video «Come si gioca»: cache del Chromium della VM spenta, narratore e personaggi a turno, musica di sottofondo, pronunce del narratore
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01A1dxvtsZx8NE9fwjXUNDBr
This commit is contained in:
@@ -15,6 +15,11 @@ export function narrazione(clip) {
|
||||
|
||||
export async function setup(d) {
|
||||
const p = d.page;
|
||||
// Niente cache: il Chromium della VM teneva i moduli JavaScript di una ripresa prima (il valzer non partiva).
|
||||
const cdp = await p.context().newCDPSession(p);
|
||||
await cdp.send("Network.enable");
|
||||
await cdp.send("Network.setCacheDisabled", { cacheDisabled: true });
|
||||
await cdp.send("Network.clearBrowserCache");
|
||||
await p.goto(URL_GIOCO);
|
||||
await p.evaluate(() => localStorage.clear());
|
||||
await p.reload();
|
||||
@@ -26,13 +31,16 @@ export function regista(d, clip) {
|
||||
const p = d.page, voce = narrazione(clip);
|
||||
let inizio = 0, dura = 0;
|
||||
const r = {
|
||||
// Una battuta del narratore: prima si lascia finire quella di prima.
|
||||
// Una battuta del narratore: prima si lascia finire quella di prima, e chi sta parlando nel gioco.
|
||||
async cue(id) {
|
||||
const resto = inizio + dura + 350 - Date.now();
|
||||
if (resto > 0) await sleep(resto);
|
||||
await r.aspetta();
|
||||
for (let i = 0; i < 300 && (await p.evaluate(() => !!game.speech || !!(window.voices?.audio && !window.voices.audio.paused && !window.voices.audio.ended))); i++) await sleep(100);
|
||||
await sleep(250);
|
||||
await d.cue(id);
|
||||
inizio = Date.now(); dura = voce[id] ?? 0;
|
||||
},
|
||||
// Prima di far parlare un personaggio, il narratore deve aver finito: le due voci non si sovrappongono.
|
||||
async aspetta() { const resto = inizio + dura + 350 - Date.now(); if (resto > 0) await sleep(resto); },
|
||||
async fine() { const resto = inizio + dura + 600 - Date.now(); if (resto > 0) await sleep(resto); },
|
||||
// Puntatore vero sulla scena (coordinate 640×360).
|
||||
async punto(x, y) {
|
||||
@@ -54,7 +62,7 @@ export function regista(d, clip) {
|
||||
}
|
||||
await sleep(pausa);
|
||||
},
|
||||
async scegli(testo) { await d.click(p.locator("#choices li", { hasText: testo }), 0.6); await r.fermi(); },
|
||||
async scegli(testo) { await r.aspetta(); await d.click(p.locator("#choices li", { hasText: testo }), 0.6); await r.fermi(); },
|
||||
// Partita nuova per Campomigliaio, introduzione saltata, dritti nella scena del gioco.
|
||||
async vaiA(scena, at) {
|
||||
await d.click(p.locator("#new-game"));
|
||||
@@ -62,10 +70,12 @@ export function regista(d, clip) {
|
||||
await d.click(p.locator('#rione [data-rione="campomigliaio"]'));
|
||||
await sleep(800);
|
||||
if (await p.isVisible("#skip-intro")) await d.click(p.locator("#skip-intro"), 0.5);
|
||||
await p.evaluate(([s, a]) => { game.go(s, a); }, [scena, at]);
|
||||
// Le battute d'apertura di Andrea (il palio sparito) qui non servono: si saltano tutte.
|
||||
await p.evaluate(([s, a]) => { for (let i = 0; i < 50 && (game.speech || game.queue.length); i++) { game.skip(); game.update(0.05); } game.go(s, a); }, [scena, at]);
|
||||
await r.fermi(1200);
|
||||
},
|
||||
async parlaCon(id) {
|
||||
await r.aspetta();
|
||||
const [x, y] = await p.evaluate((id) => { const h = game.hotspot(id); return [h.box[0] + h.box[2] / 2, h.box[1] + h.box[3] / 2]; }, id);
|
||||
await r.clicca([x, y]);
|
||||
await r.fermi();
|
||||
|
||||
Reference in New Issue
Block a user