Files

91 lines
4.4 KiB
JavaScript

// Copione del video «Come si gioca: le bocce» (video/SCALETTA-CARTE.md, clip 4).
// Giro: video/narra.py, poi rec.mjs come in video/SCALETTA.md, poi video/monta.py <cartella> --tutorial.
import { c, sleep, setup as base, regista } from "./tutorial-comune.mjs";
export const title = { it: "Come si gioca · le bocce", en: "Come si gioca · le bocce" };
export const cues = [
c("dove", "Le bocce si giocano al pallaio, accanto al tennis della chiesa. Mariano, il campione, sfida chiunque"),
c("livello", "Si sceglie quanto deve impegnarsi: alla bona, seria, o a fassi male"),
c("campo", "Il campo visto da dietro: in fondo c'è il pallino, e a sinistra il dettaglio, per vedere da vicino chi è più accosto"),
c("mira", "Per mirare si tocca il campo, o il dettaglio vicino al pallino. Il cerchio azzurro dice dove si fermerebbe la boccia"),
c("forza", "Poi si regola la forza col cursore, e si preme Lancia"),
c("turno", "Tira sempre chi non ha il punto. Chi è dietro può accostare, oppure bocciare: colpire la boccia dell'altro per toglierla di lì"),
c("tieni", "C'è anche un altro modo: si tiene premuto sul campo, la forza sale, e lasciando parte la boccia. Vanno bene anche le frecce e la barra spaziatrice"),
c("punti", "Tre bocce a testa. Alla fine fa un punto ogni boccia più vicina al pallino della migliore dell'avversario"),
c("fine", "E se batti Mariano, ti porta a Brento Sanico. Buona partita!"),
];
export const setup = base;
export async function run(d) {
const p = d.page, r = regista(d, "tutorial-bocce");
await r.ascolta();
await r.vaiA("tennis_chiesa", [430, 310]);
await r.cue("dove");
await r.parlaCon("mariano");
await r.scegli("Facciamo una partita");
await r.cue("livello");
await r.scegli("Alla bona.");
// Una mano fissa: accostando bene, Andrea fa tre punti (anche se il tiro a pressione viene un po' corto o lungo).
await p.evaluate(async () => {
const { newBocce } = await import("/src/engine/bocce.js");
game.closeup = { id: "bocce", ...newBocce(9, { level: "bona" }) };
});
await sleep(800);
await p.waitForFunction(() => window.music?.want === "assets/audio/bocce.mp3", null, { timeout: 10000 });
await r.cue("campo");
await r.muovi([300, 200], 1.0); await sleep(400); await r.muovi([90, 170], 1.0);
// Dove mirare: poco prima del pallino, così la boccia si ferma accosto (il cerchio azzurro ci finisce sopra).
const mira = () => p.evaluate(async () => {
const B = await import("/src/engine/bocce.js"), c = game.closeup, u = c.jack.u - 0.55, w = c.jack.w;
const s = B.project(u, w);
return { at: [s.x, s.y], u, w, power: B.powerFor(Math.hypot(u, w) - 0.29) };
});
const tocca = async () => {
for (let i = 0; i < 600; i++) {
const s = await p.evaluate(async () => {
const { canThrow } = await import("/src/engine/bocce.js");
return game.closeup.step === "result" ? "fine" : canThrow(game.closeup) && !game.speech ? "tocca" : "aspetta";
});
if (s !== "aspetta") return s === "tocca";
await sleep(150);
}
return false;
};
let tiro = 0;
while (await tocca()) {
tiro++;
const m = await mira();
if (tiro === 1) await r.cue("mira");
if (tiro < 3) {
// Mira col clic, forza col cursore, poi Lancia.
await r.clicca(m.at, 0.8);
await p.evaluate(async ({ u, w }) => (await import("/src/engine/bocce.js")).aim(game.closeup, u, w), m);
if (tiro === 1) await r.cue("forza");
await d.hover(p.locator("#bocce-power"), 0.6);
await p.locator("#bocce-power").fill(String(Math.round(m.power * 100)));
await p.evaluate(async (v) => (await import("/src/engine/bocce.js")).setPower(game.closeup, v), m.power);
await sleep(600);
await d.click(p.locator("#bocce-throw"), 0.6);
if (tiro === 1) await r.cue("turno");
} else {
// L'ultima tenendo premuto: la forza sale finché non si lascia.
await r.cue("tieni");
await r.muovi(m.at, 0.8);
const [a, b] = await r.punto(...m.at);
d.vm(`DISPLAY=:0 xdotool mousemove ${Math.round(a)} ${Math.round(b)} mousedown 1 sleep ${(m.power * 1.6).toFixed(2)} mouseup 1`);
}
await p.locator("#scene").scrollIntoViewIfNeeded();
}
await p.waitForFunction(() => game.closeup.step === "result", null, { timeout: 90000 });
await sleep(1000);
await r.cue("punti");
await r.cue("fine");
await r.aspetta();
await d.click(p.locator("#closeup-close"), 0.6);
await r.fermi(800);
await r.fine();
await r.salvaAudio();
}