Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8693bff0c7 | ||
|
|
c6812db291 | ||
|
|
670626afa5 | ||
|
|
9bf41d01af | ||
|
|
16252fb04a | ||
|
|
99d4dede80 | ||
|
|
36eda83fe4 |
Binary file not shown.
|
After Width: | Height: | Size: 75 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 56 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 71 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1887,6 +1887,38 @@
|
|||||||
"file": "andrea-d38b6e49ef.mp3",
|
"file": "andrea-d38b6e49ef.mp3",
|
||||||
"sec": 3.49
|
"sec": 3.49
|
||||||
},
|
},
|
||||||
|
"andrea|Lo zio Mario nel suo orto, col sole che va giù dietro la casa.": {
|
||||||
|
"file": "andrea-9309e50d5c.mp3",
|
||||||
|
"sec": 3.78
|
||||||
|
},
|
||||||
|
"zio_mario|Ti s'aspetta a cena, che c'è la vitella di maiale.": {
|
||||||
|
"file": "zio_mario-39ff0c666f.mp3",
|
||||||
|
"sec": 2.71
|
||||||
|
},
|
||||||
|
"andrea|Non ti avevo visto, pensavo tu fossi andato all'estero.": {
|
||||||
|
"file": "andrea-f847f224df.mp3",
|
||||||
|
"sec": 3.35
|
||||||
|
},
|
||||||
|
"zio_mario|Io ho girato tanto... il Falcione.": {
|
||||||
|
"file": "zio_mario-d0d592db52.mp3",
|
||||||
|
"sec": 2.73
|
||||||
|
},
|
||||||
|
"andrea|Zio, che sei stanco?": {
|
||||||
|
"file": "andrea-21195c6cac.mp3",
|
||||||
|
"sec": 2.31
|
||||||
|
},
|
||||||
|
"zio_mario|No, dormo!": {
|
||||||
|
"file": "zio_mario-a852e9c43f.mp3",
|
||||||
|
"sec": 1.19
|
||||||
|
},
|
||||||
|
"andrea|Zio, a me mi garba Michael Jackson!": {
|
||||||
|
"file": "andrea-599b75d7c7.mp3",
|
||||||
|
"sec": 2.6
|
||||||
|
},
|
||||||
|
"zio_mario|Mai col gesso!": {
|
||||||
|
"file": "zio_mario-5773e3350f.mp3",
|
||||||
|
"sec": 1.13
|
||||||
|
},
|
||||||
"andrea|Le case coi balconi pieni di vasi: qui ogni finestra è un giardino.": {
|
"andrea|Le case coi balconi pieni di vasi: qui ogni finestra è un giardino.": {
|
||||||
"file": "andrea-ec81875c47.mp3",
|
"file": "andrea-ec81875c47.mp3",
|
||||||
"sec": 5.22
|
"sec": 5.22
|
||||||
@@ -3255,9 +3287,9 @@
|
|||||||
"file": "bertovo-ca941bee91.mp3",
|
"file": "bertovo-ca941bee91.mp3",
|
||||||
"sec": 5.41
|
"sec": 5.41
|
||||||
},
|
},
|
||||||
"vannino|M'hai pelato, ragazzo. Nel 1997 un ci si vedeva da queste parti, con quella faccia.": {
|
"vannino|Tu m'ha pelato. La prossima volta porta il Barone.": {
|
||||||
"file": "vannino-e68fb40eba.mp3",
|
"file": "vannino-2267bb5adf.mp3",
|
||||||
"sec": 7.85
|
"sec": 3.18
|
||||||
},
|
},
|
||||||
"pierino_parigi|Le fiches restano al banco. E tu torna quando hai imparato a bluffare.": {
|
"pierino_parigi|Le fiches restano al banco. E tu torna quando hai imparato a bluffare.": {
|
||||||
"file": "pierino_parigi-a80d04fe5b.mp3",
|
"file": "pierino_parigi-a80d04fe5b.mp3",
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -36,6 +36,7 @@ ne è un'opera derivata. Le foto scattate da Andrea non hanno problemi; quelle p
|
|||||||
| `characters/zio_mario.png` | Codex | `foto/zio-mario.png` | Andrea (29 ottobre) | sì (famiglia di Andrea) |
|
| `characters/zio_mario.png` | Codex | `foto/zio-mario.png` | Andrea (29 ottobre) | sì (famiglia di Andrea) |
|
||||||
| `terrazza-cardetole.png` | Codex (dalla foto, poi il terrazzo davanti) | `cardetole-finestra.jpg` | Andrea (29 ottobre) | **da decidere**: come `cardetole.png`, dice dove abita Andrea |
|
| `terrazza-cardetole.png` | Codex (dalla foto, poi il terrazzo davanti) | `cardetole-finestra.jpg` | Andrea (29 ottobre) | **da decidere**: come `cardetole.png`, dice dove abita Andrea |
|
||||||
| `closeups/muro-cerbottana.png` | Codex, solo testo (stile dalla piazza) | nessuna | — | sì |
|
| `closeups/muro-cerbottana.png` | Codex, solo testo (stile dalla piazza) | nessuna | — | sì |
|
||||||
|
| `closeups/macchina-dietro.png`, `macchina-lampi.png`, `macchina-davanti.png` | Codex, dallo sprite della macchina del tempo | nessuna | — | sì |
|
||||||
| `closeups/campone-condor.png` | Codex, dallo sfondo del campone delle poste | nessuna | — | sì |
|
| `closeups/campone-condor.png` | Codex, dallo sfondo del campone delle poste | nessuna | — | sì |
|
||||||
| `barrettino-1997.png`, `closeups/cruscotto-tempo.png` | Codex, solo testo | nessuna | — | sì |
|
| `barrettino-1997.png`, `closeups/cruscotto-tempo.png` | Codex, solo testo | nessuna | — | sì |
|
||||||
| `characters/vannino.png`, `characters/pierino_parigi.png` | Codex, dalla descrizione di Andrea (niente foto) | nessuna | — | sì (Pierino: consenso del figlio Marco) |
|
| `characters/vannino.png`, `characters/pierino_parigi.png` | Codex, dalla descrizione di Andrea (niente foto) | nessuna | — | sì (Pierino: consenso del figlio Marco) |
|
||||||
|
|||||||
@@ -18,6 +18,12 @@ Online su 50037.manzolo.it tutto fino agli effetti ambientali di Codex. Aperto,
|
|||||||
|
|
||||||
## Dove siamo arrivati
|
## Dove siamo arrivati
|
||||||
|
|
||||||
|
- **La macchina del tempo da fuori (30 ottobre)**: dopo il cruscotto, la partenza giù per Via Liguri Magelli
|
||||||
|
(primo piano `corsa`, `src/engine/corsa.js`): accelera, il fulmine la prende, il bianco, e restano due sgommate di
|
||||||
|
fuoco che bruciano e si spengono; al ritorno dal 1997 l'arrivo: il fulmine in fondo alla strada, lei viene avanti e
|
||||||
|
ci passa accanto lasciando le strisce. La macchina da dietro e davanti (coi lampi) è di Codex.
|
||||||
|
- **Lo zio Mario negli orti al tramonto (30 ottobre)**: dal tramonto (`indizio_regolo`) non è più davanti alla
|
||||||
|
Ghiacciomobile ma accanto al suo orto (`orti_zio_mario`), con una battuta provvisoria [DA ANDREA].
|
||||||
- **La Condor al campone delle poste (29 ottobre)**: la gara col Taglia (Andrea Tagliaferri, consenso dato) con la
|
- **La Condor al campone delle poste (29 ottobre)**: la gara col Taglia (Andrea Tagliaferri, consenso dato) con la
|
||||||
pistola ad aria compressa coi pallini gialli (`condor.js`, `condor-render.js`, primo piano `condor`, sfondo di Codex).
|
pistola ad aria compressa coi pallini gialli (`condor.js`, `condor-render.js`, primo piano `condor`, sfondo di Codex).
|
||||||
Come la cerbottana: il mirino ondeggia col respiro; tenere premuto trattiene il fiato (il mirino si ferma), lasciare
|
Come la cerbottana: il mirino ondeggia col respiro; tenere premuto trattiene il fiato (il mirino si ferma), lasciare
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "leggenda-del-regolo",
|
"name": "leggenda-del-regolo",
|
||||||
"version": "0.1.54",
|
"version": "0.1.56",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -0,0 +1,121 @@
|
|||||||
|
// La macchina del tempo vista da fuori (story.closeups, type 'corsa'; Andrea, 30 ottobre). In partenza ('parti') va via
|
||||||
|
// giù per la strada accelerando, il fulmine la prende, il bianco, e restano due sgommate di fuoco che bruciano e si
|
||||||
|
// spengono. All'arrivo ('arriva') il fulmine in fondo alla strada, e lei viene avanti e ci passa accanto, lasciando le
|
||||||
|
// stesse strisce (davanti a noi: dietro alla macchina non si vedrebbero). Sopra lo sfondo della scena (`scene`), coi fotogrammi di Codex (`frames`: dietro, dietro coi lampi,
|
||||||
|
// davanti coi lampi). Unità: i pixel della scena 640×360.
|
||||||
|
|
||||||
|
// I tempi, in secondi. Partenza: ferma che si carica, la corsa, il fulmine, il bianco, le fiamme, la fine.
|
||||||
|
export const PARTI = { charge: 0.6, run: 2.2, bolt: 2.3, flash: 0.35, burn: 4.6, end: 5.2 };
|
||||||
|
// Arrivo: il fulmine in fondo, la corsa verso di noi fin fuori dal quadro, le fiamme, la fine.
|
||||||
|
export const ARRIVA = { bolt: 0.3, flash: 0.35, run: 1.5, burn: 4, end: 4.6 };
|
||||||
|
|
||||||
|
const lerp = (a, b, k) => a + (b - a) * k;
|
||||||
|
const clamp01 = k => Math.max(0, Math.min(1, k));
|
||||||
|
// Dove sta la macchina a un punto `k` del percorso (0 vicina, 1 in fondo): posizione delle ruote e grandezza.
|
||||||
|
export function along(def, k) {
|
||||||
|
const [a, b] = def.path;
|
||||||
|
return { x: lerp(a[0], b[0], k), y: lerp(a[1], b[1], k), scale: lerp(a[2], b[2], k) };
|
||||||
|
}
|
||||||
|
// Il punto del percorso al tempo t: in partenza accelera (da fermo); all'arrivo viene avanti dal fondo fin oltre il
|
||||||
|
// punto 0 (fuori dal quadro, accanto a noi).
|
||||||
|
export function progress(c, def) {
|
||||||
|
if (def.mode === 'arriva') return 1 - clamp01((c.t - ARRIVA.bolt) / ARRIVA.run);
|
||||||
|
const k = clamp01((c.t - PARTI.charge) / (PARTI.run - PARTI.charge));
|
||||||
|
return Math.min(0.92, k * k);
|
||||||
|
}
|
||||||
|
// Si vede la macchina? In partenza fino al fulmine; all'arrivo dal fulmine in poi.
|
||||||
|
export function carShown(c, def) {
|
||||||
|
return def.mode === 'arriva' ? c.t >= ARRIVA.bolt + 0.05 && c.t < ARRIVA.bolt + ARRIVA.run : c.t < PARTI.bolt + 0.05;
|
||||||
|
}
|
||||||
|
// Dove arriva il fulmine: sulla macchina in partenza, in fondo alla strada all'arrivo.
|
||||||
|
export function boltAt(def) { return def.mode === 'arriva' ? along(def, 1) : along(def, progress({ t: PARTI.bolt }, def)); }
|
||||||
|
const T = def => def.mode === 'arriva' ? ARRIVA : PARTI;
|
||||||
|
|
||||||
|
export function newCorsa(id) { return { id, t: 0, age: 0, events: [] }; }
|
||||||
|
// Il tempo che passa e i suoni; vero quando è finita.
|
||||||
|
export function updateCorsa(c, def, dt) {
|
||||||
|
c.t += dt;
|
||||||
|
const times = T(def);
|
||||||
|
if (def.mode !== 'arriva' && !c.charge && c.t >= 0.1) { c.charge = true; c.events.push({ kind: 'gara-turbo', power: 1 }); }
|
||||||
|
if (!c.boom && c.t >= times.bolt) { c.boom = true; c.events.push({ kind: 'corsa-tuono', power: 1 }); }
|
||||||
|
if (!c.fire && c.t >= (def.mode === 'arriva' ? ARRIVA.bolt + 0.2 : PARTI.charge + 0.3)) { c.fire = true; c.events.push({ kind: 'corsa-fuoco', power: 1 }); }
|
||||||
|
return c.t >= times.end;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Le due ruote posteriori (o anteriori) a un punto del percorso: una a sinistra e una a destra.
|
||||||
|
function wheels(def, k) {
|
||||||
|
const p = along(def, k), half = def.track * p.scale;
|
||||||
|
return [[p.x - half, p.y], [p.x + half, p.y]];
|
||||||
|
}
|
||||||
|
// Le sgommate di fuoco: da dove è partita a dove è arrivata, fiammelle che tremano, più piccole in fondo, che si
|
||||||
|
// spengono dopo `burn`.
|
||||||
|
function fire(ctx, c, def) {
|
||||||
|
const times = T(def), shown = def.mode === 'arriva' ? [Math.max(progress(c, def), 0), 1] : [0, progress({ t: Math.min(c.t, times.bolt) }, def)];
|
||||||
|
const fade = c.t < times.burn ? 1 : clamp01(1 - (c.t - times.burn) / (times.end - times.burn));
|
||||||
|
if (fade <= 0 || shown[1] - shown[0] < 0.005) return;
|
||||||
|
for (let side = 0; side < 2; side++) {
|
||||||
|
// Prima il segno nero bruciato, poi le fiamme sopra.
|
||||||
|
const [a, b] = [wheels(def, shown[0])[side], wheels(def, shown[1])[side]];
|
||||||
|
ctx.strokeStyle = `rgba(30,18,10,${0.7 * Math.max(fade, 0.5)})`; ctx.lineWidth = 4; ctx.beginPath(); ctx.moveTo(a[0], a[1]); ctx.lineTo(b[0], b[1]); ctx.stroke();
|
||||||
|
const n = 70;
|
||||||
|
for (let i = 0; i <= n; i++) {
|
||||||
|
const k = lerp(shown[0], shown[1], i / n), [x, y] = wheels(def, k)[side], s = Math.max(0.12, along(def, k).scale);
|
||||||
|
// Lingue di fuoco di altezza diversa, che tremano: rosso fuori, arancio, il cuore giallo.
|
||||||
|
const flick = 0.55 + 0.45 * Math.sin(c.t * 19 + i * 2.3 + side * 2) * Math.sin(c.t * 7 + i * 0.9);
|
||||||
|
const h = (16 + 22 * flick) * s * fade, w = Math.max(2, 9 * s);
|
||||||
|
if (h < 1.5) continue;
|
||||||
|
ctx.fillStyle = `rgba(255,120,30,${0.18 * fade})`; ctx.fillRect(Math.round(x - w), Math.round(y - h * 1.2), Math.ceil(w * 2), Math.ceil(h * 1.2));
|
||||||
|
ctx.fillStyle = `rgba(220,50,20,${0.9 * fade})`; ctx.fillRect(Math.round(x - w / 2), Math.round(y - h), Math.ceil(w), Math.ceil(h));
|
||||||
|
ctx.fillStyle = `rgba(255,${Math.round(140 + 60 * flick)},30,${0.95 * fade})`; ctx.fillRect(Math.round(x - w / 3), Math.round(y - h * 0.7), Math.ceil(w * 0.66), Math.ceil(h * 0.7));
|
||||||
|
ctx.fillStyle = `rgba(255,245,170,${fade})`; ctx.fillRect(Math.round(x - w / 6), Math.round(y - h * 0.35), Math.max(1, Math.ceil(w / 3)), Math.ceil(h * 0.35));
|
||||||
|
// Un filo di fumo che sale quando le fiamme calano.
|
||||||
|
if (c.t > times.burn - 1 && i % 8 === 0) {
|
||||||
|
ctx.fillStyle = `rgba(90,90,96,${0.25 * fade})`;
|
||||||
|
ctx.fillRect(Math.round(x - 2 * s), Math.round(y - h - 6 * s - ((c.t * 18 + i) % 14) * s), Math.ceil(4 * s), Math.ceil(4 * s));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Il fulmine: una saetta spezzata dal cielo fino al punto, con due rami.
|
||||||
|
function bolt(ctx, c, def) {
|
||||||
|
const times = T(def), dt = c.t - times.bolt;
|
||||||
|
if (dt < -0.12 || dt > 0.28) return;
|
||||||
|
const p = boltAt(def), seed = Math.floor(c.t * 30);
|
||||||
|
ctx.save();
|
||||||
|
for (const [width, color] of [[6, 'rgba(140,200,255,0.5)'], [2, '#ffffff']]) {
|
||||||
|
ctx.strokeStyle = color; ctx.lineWidth = width; ctx.beginPath();
|
||||||
|
let x = p.x + 40, y = 0; ctx.moveTo(x, y);
|
||||||
|
const steps = 9;
|
||||||
|
for (let i = 1; i <= steps; i++) {
|
||||||
|
x = lerp(p.x + 40, p.x, i / steps) + (i < steps ? ((seed * (i + 5) * 53) % 30) - 15 : 0);
|
||||||
|
y = lerp(0, p.y - 12 * p.scale, i / steps); ctx.lineTo(x, y);
|
||||||
|
}
|
||||||
|
ctx.stroke();
|
||||||
|
}
|
||||||
|
ctx.restore();
|
||||||
|
}
|
||||||
|
|
||||||
|
export function drawCorsa(ctx, c, def, { bg, frames, tint }) {
|
||||||
|
const times = T(def);
|
||||||
|
ctx.save(); ctx.imageSmoothingEnabled = false;
|
||||||
|
// La strada trema un po' quando la macchina si carica e quando arriva il fulmine.
|
||||||
|
const shake = (def.mode !== 'arriva' && c.t < PARTI.charge + 0.4 ? 1.5 : 0) + (Math.abs(c.t - times.bolt) < 0.25 ? 3 : 0);
|
||||||
|
ctx.translate(Math.round(Math.sin(c.t * 57) * shake), Math.round(Math.cos(c.t * 43) * shake));
|
||||||
|
if (bg) ctx.drawImage(bg, 0, 0, 640, 360); else { ctx.fillStyle = '#4a4a50'; ctx.fillRect(0, 0, 640, 360); }
|
||||||
|
if (tint) { ctx.fillStyle = tint; ctx.fillRect(0, 0, 640, 360); }
|
||||||
|
fire(ctx, c, def);
|
||||||
|
if (carShown(c, def)) {
|
||||||
|
const k = progress(c, def), p = along(def, k);
|
||||||
|
// Da dietro: coi lampi mentre si carica e quando corre forte; davanti (all'arrivo) coi lampi finché frena.
|
||||||
|
const img = def.mode === 'arriva' ? frames?.davanti : c.t > PARTI.charge * 0.5 && Math.floor(c.t * 14) % 3 !== 0 ? frames?.lampi : frames?.dietro;
|
||||||
|
if (img) {
|
||||||
|
const w = def.width * p.scale, h = w * img.height / img.width;
|
||||||
|
ctx.drawImage(img, Math.round(p.x - w / 2), Math.round(p.y - h), Math.round(w), Math.round(h));
|
||||||
|
} else { ctx.fillStyle = '#c8ccd2'; ctx.fillRect(Math.round(p.x - 40 * p.scale), Math.round(p.y - 40 * p.scale), Math.round(80 * p.scale), Math.round(40 * p.scale)); }
|
||||||
|
}
|
||||||
|
bolt(ctx, c, def);
|
||||||
|
ctx.restore();
|
||||||
|
// Il bianco del fulmine, che sfuma.
|
||||||
|
const f = c.t - times.bolt;
|
||||||
|
if (f >= 0 && f < times.flash) { ctx.fillStyle = `rgba(255,255,255,${1 - f / times.flash})`; ctx.fillRect(0, 0, 640, 360); }
|
||||||
|
}
|
||||||
+4
-1
@@ -12,6 +12,7 @@ import * as scopa from './scopa.js';
|
|||||||
import * as gara from './gara.js';
|
import * as gara from './gara.js';
|
||||||
import * as micro from './micro.js';
|
import * as micro from './micro.js';
|
||||||
import * as cerbottana from './cerbottana.js';
|
import * as cerbottana from './cerbottana.js';
|
||||||
|
import { newCorsa, updateCorsa } from './corsa.js';
|
||||||
import * as condor from './condor.js';
|
import * as condor from './condor.js';
|
||||||
import * as poker from './poker.js';
|
import * as poker from './poker.js';
|
||||||
|
|
||||||
@@ -325,7 +326,7 @@ export class Game {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// Il viaggio si chiude da solo alla fine (o uscendo prima): si arriva comunque.
|
// Il viaggio si chiude da solo alla fine (o uscendo prima): si arriva comunque.
|
||||||
if (def?.type === 'viaggio') { this.queue.unshift(...def.complete); return true; }
|
if (def?.type === 'viaggio' || def?.type === 'corsa') { this.queue.unshift(...def.complete); return true; }
|
||||||
// I minigiochi: a partita finita (risultato deciso, anche se il conteggio si sta ancora mostrando) la battuta
|
// I minigiochi: a partita finita (risultato deciso, anche se il conteggio si sta ancora mostrando) la battuta
|
||||||
// di chi ha vinto; uscendo prima, quella di chi lascia.
|
// di chi ha vinto; uscendo prima, quella di chi lascia.
|
||||||
if (MINIGAMES[def?.type]) {
|
if (MINIGAMES[def?.type]) {
|
||||||
@@ -486,6 +487,7 @@ export class Game {
|
|||||||
if (c) {
|
if (c) {
|
||||||
if (this.story.closeups[c.id].type === 'torch') { this.updateTorch(dt); return; }
|
if (this.story.closeups[c.id].type === 'torch') { this.updateTorch(dt); return; }
|
||||||
if (this.story.closeups[c.id].type === 'viaggio') { this.updateTrip(dt); return; }
|
if (this.story.closeups[c.id].type === 'viaggio') { this.updateTrip(dt); return; }
|
||||||
|
if (this.story.closeups[c.id].type === 'corsa') { if (updateCorsa(c, this.story.closeups[c.id], dt)) this.closeupClose(); return; }
|
||||||
const m = this.minigame();
|
const m = this.minigame();
|
||||||
if (m) {
|
if (m) {
|
||||||
m.update(c, dt);
|
m.update(c, dt);
|
||||||
@@ -528,6 +530,7 @@ export class Game {
|
|||||||
const type = this.story.closeups[e.closeup].type;
|
const type = this.story.closeups[e.closeup].type;
|
||||||
this.closeup = type === 'torch' ? { id: e.closeup, step: 'search', t: 0, age: 0, found: 0, dwell: 0, beam: [320, 180] }
|
this.closeup = type === 'torch' ? { id: e.closeup, step: 'search', t: 0, age: 0, found: 0, dwell: 0, beam: [320, 180] }
|
||||||
: type === 'viaggio' ? { id: e.closeup, t: 0, age: 0, events: [], typed: 0 }
|
: type === 'viaggio' ? { id: e.closeup, t: 0, age: 0, events: [], typed: 0 }
|
||||||
|
: type === 'corsa' ? newCorsa(e.closeup)
|
||||||
// `level`: «Alla bona», «Seria» o «A fassi male», scelto nel dialogo con l'avversario.
|
// `level`: «Alla bona», «Seria» o «A fassi male», scelto nel dialogo con l'avversario.
|
||||||
// `decks`: il mazzo da usare quando il suo flag è acceso (briscola: le napoletane al posto delle toscane).
|
// `decks`: il mazzo da usare quando il suo flag è acceso (briscola: le napoletane al posto delle toscane).
|
||||||
: MINIGAMES[type] ? { id: e.closeup, ...MINIGAMES[type].create(Math.floor(Math.random() * 4294967296), e.level,
|
: MINIGAMES[type] ? { id: e.closeup, ...MINIGAMES[type].create(Math.floor(Math.random() * 4294967296), e.level,
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import { drawPesca } from './pesca-render.js';
|
|||||||
import { drawGara } from './gara-render.js';
|
import { drawGara } from './gara-render.js';
|
||||||
import { drawMicro } from './micro-render.js';
|
import { drawMicro } from './micro-render.js';
|
||||||
import { drawCerbottana } from './cerbottana-render.js';
|
import { drawCerbottana } from './cerbottana-render.js';
|
||||||
|
import { drawCorsa } from './corsa.js';
|
||||||
import { drawCondor } from './condor-render.js';
|
import { drawCondor } from './condor-render.js';
|
||||||
import { drawPoker } from './poker-render.js';
|
import { drawPoker } from './poker-render.js';
|
||||||
import { drawViaggio } from './viaggio.js';
|
import { drawViaggio } from './viaggio.js';
|
||||||
@@ -686,6 +687,16 @@ function drawCloseup(ctx, game, time) {
|
|||||||
drawViaggio(ctx, c, def, backgrounds.get(def.picture));
|
drawViaggio(ctx, c, def, backgrounds.get(def.picture));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// La macchina del tempo da fuori: lo sfondo di adesso della scena, con la luce della fase del giorno.
|
||||||
|
if (def.type === 'corsa') {
|
||||||
|
const bg = game.backdrop(game.story.scenes[def.scene]), frames = {};
|
||||||
|
for (const [k, src] of [[bg, bg], ...Object.entries(def.frames)]) {
|
||||||
|
if (!backgrounds.has(src)) loadBackground(src);
|
||||||
|
if (k !== bg) frames[k] = backgrounds.get(src);
|
||||||
|
}
|
||||||
|
drawCorsa(ctx, c, def, { bg: backgrounds.get(bg), frames, tint: game.phase()?.tint });
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (def.type === 'torch') {
|
if (def.type === 'torch') {
|
||||||
if (!backgrounds.has(def.picture)) loadBackground(def.picture);
|
if (!backgrounds.has(def.picture)) loadBackground(def.picture);
|
||||||
drawTorch(ctx, c, def, backgrounds.get(def.picture));
|
drawTorch(ctx, c, def, backgrounds.get(def.picture));
|
||||||
|
|||||||
@@ -145,6 +145,9 @@ export class Soundscape {
|
|||||||
else if (kind === 'condor-palloncino') { this.noiseSound(0.12, 1800, 0.14, { pan }); this.tone(140, 60, 0.08, 0.08, 0, pan); }
|
else if (kind === 'condor-palloncino') { this.noiseSound(0.12, 1800, 0.14, { pan }); this.tone(140, 60, 0.08, 0.08, 0, pan); }
|
||||||
else if (kind === 'condor-plastica') { this.tone(1300, 900, 0.06, 0.05, 0, pan); this.noiseSound(0.05, 2600, 0.03, { pan }); }
|
else if (kind === 'condor-plastica') { this.tone(1300, 900, 0.06, 0.05, 0, pan); this.noiseSound(0.05, 2600, 0.03, { pan }); }
|
||||||
else if (kind === 'condor-lancio') this.noiseSound(0.2, 700, 0.03, { pan });
|
else if (kind === 'condor-lancio') this.noiseSound(0.2, 700, 0.03, { pan });
|
||||||
|
// La macchina del tempo: il tuono del fulmine e lo sfrigolio delle sgommate di fuoco.
|
||||||
|
else if (kind === 'corsa-tuono') { this.noiseSound(0.9, 400, 0.16, { pan }); this.tone(90, 40, 0.8, 0.1, 0, pan); }
|
||||||
|
else if (kind === 'corsa-fuoco') this.noiseSound(1.6, 2400, 0.05, { pan });
|
||||||
else if (kind === 'cerbottana-tosse') { this.noiseSound(0.18, 900, 0.08, { pan }); this.tone(260, 140, 0.12, 0.06, 0.25, pan); this.tone(240, 120, 0.1, 0.05, 0.3, pan); }
|
else if (kind === 'cerbottana-tosse') { this.noiseSound(0.18, 900, 0.08, { pan }); this.tone(260, 140, 0.12, 0.06, 0.25, pan); this.tone(240, 120, 0.1, 0.05, 0.3, pan); }
|
||||||
// Le macchinine: il dito che spinge, le ruote sull'asfalto, l'urto di plastica, fuori pista, il traguardo.
|
// Le macchinine: il dito che spinge, le ruote sull'asfalto, l'urto di plastica, fuori pista, il traguardo.
|
||||||
else if (kind === 'micro-spinta') { this.tone(1200, 500, 0.04, 0.04 + strength * 0.04, 0, pan); this.noiseSound(0.04, 2600, 0.04, { pan }); }
|
else if (kind === 'micro-spinta') { this.tone(1200, 500, 0.04, 0.04 + strength * 0.04, 0, pan); this.noiseSound(0.04, 2600, 0.04, { pan }); }
|
||||||
|
|||||||
@@ -241,7 +241,7 @@ export const ambience = {
|
|||||||
{ type: 'insect', kind: 'dragonfly', phase: day, area: [440, 228, 110, 30], every: 31000, duration: 8500, offset: 15000 },
|
{ type: 'insect', kind: 'dragonfly', phase: day, area: [440, 228, 110, 30], every: 31000, duration: 8500, offset: 15000 },
|
||||||
],
|
],
|
||||||
orti_zio_mario: [
|
orti_zio_mario: [
|
||||||
{ type: 'clouds', area: [80, 20, 500, 90], count: 3, big: true },
|
{ type: 'clouds', area: [60, 20, 330, 70], count: 3, big: true }, // solo fino all'abete: dentro le fronde che ondeggiano le nuvole si tagliano
|
||||||
{ type: 'birds', phase: day, area: [300, 30, 250, 60], count: 3, every: 24000, duration: 5000, offset: 2000 },
|
{ type: 'birds', phase: day, area: [300, 30, 250, 60], count: 3, every: 24000, duration: 5000, offset: 2000 },
|
||||||
{ type: 'sway', rects: [[180, 10, 140, 180], [430, 10, 210, 240]], amount: 2 },
|
{ type: 'sway', rects: [[180, 10, 140, 180], [430, 10, 210, 240]], amount: 2 },
|
||||||
butterfly([10, 240, 140, 50], 8000),
|
butterfly([10, 240, 140, 50], 8000),
|
||||||
|
|||||||
+41
-1
@@ -43,11 +43,19 @@ const torchHints = [{
|
|||||||
}],
|
}],
|
||||||
}];
|
}];
|
||||||
|
|
||||||
|
// La macchina del tempo che corre, vista da dietro e (all'arrivo) davanti: larga `width` pixel da vicino, le ruote a
|
||||||
|
// `track` della larghezza dal centro.
|
||||||
|
const MACCHINA_CORSA = {
|
||||||
|
frames: { dietro: 'assets/closeups/macchina-dietro.png', lampi: 'assets/closeups/macchina-lampi.png', davanti: 'assets/closeups/macchina-davanti.png' },
|
||||||
|
width: 220, track: 75,
|
||||||
|
};
|
||||||
|
|
||||||
// Il ritorno dal 1997, dalla porta o dal pulsante «Torna al 2007»: la macchina del tempo sparisce, e per rifare il
|
// Il ritorno dal 1997, dalla porta o dal pulsante «Torna al 2007»: la macchina del tempo sparisce, e per rifare il
|
||||||
// viaggio si richiede all'Arcu (Andrea, 29 ottobre).
|
// viaggio si richiede all'Arcu (Andrea, 29 ottobre).
|
||||||
const RITORNO_2007 = [
|
const RITORNO_2007 = [
|
||||||
{ say: 'Si torna nel 2007. Ciao Vannino, ciao Pierino.' },
|
{ say: 'Si torna nel 2007. Ciao Vannino, ciao Pierino.' },
|
||||||
{ go: 'via_liguri_magelli', at: [212, 280], face: 'down' },
|
{ go: 'via_liguri_magelli', at: [212, 280], face: 'down' },
|
||||||
|
{ closeup: 'arrivo' },
|
||||||
{ unset: 'macchina_trappola' },
|
{ unset: 'macchina_trappola' },
|
||||||
{ say: 'Riportata dove l\'ho presa. Se ti riviene voglia di pokerini, chiedi.', who: 'arcu', pose: 'explain' },
|
{ say: 'Riportata dove l\'ho presa. Se ti riviene voglia di pokerini, chiedi.', who: 'arcu', pose: 'explain' },
|
||||||
];
|
];
|
||||||
@@ -249,13 +257,25 @@ export const story = {
|
|||||||
picture: 'assets/closeups/cruscotto-tempo.png',
|
picture: 'assets/closeups/cruscotto-tempo.png',
|
||||||
display: [220, 158, 212, 62],
|
display: [220, 158, 212, 62],
|
||||||
date: '10/07/1997 18:30',
|
date: '10/07/1997 18:30',
|
||||||
|
complete: [{ closeup: 'partenza' }],
|
||||||
|
},
|
||||||
|
// La partenza vista da fuori: giù per Via Liguri Magelli, il fulmine e le sgommate di fuoco; e l'arrivo, al
|
||||||
|
// ritorno dal 1997 (Andrea, 30 ottobre; la macchina da dietro e davanti è di Codex).
|
||||||
|
partenza: {
|
||||||
|
type: 'corsa', mode: 'parti', scene: 'via_liguri_magelli', ...MACCHINA_CORSA,
|
||||||
|
path: [[215, 350, 1], [252, 192, 0.05]],
|
||||||
complete: [{ go: 'barrettino_1997', at: [320, 330], face: 'up' }],
|
complete: [{ go: 'barrettino_1997', at: [320, 330], face: 'up' }],
|
||||||
},
|
},
|
||||||
|
arrivo: {
|
||||||
|
type: 'corsa', mode: 'arriva', scene: 'via_liguri_magelli', ...MACCHINA_CORSA,
|
||||||
|
path: [[110, 470, 2.2], [252, 192, 0.05]],
|
||||||
|
complete: [],
|
||||||
|
},
|
||||||
// Il pokerino del Barrettino con Vannino e Pierino (Andrea, 29 ottobre). [DA ANDREA: le battute]
|
// Il pokerino del Barrettino con Vannino e Pierino (Andrea, 29 ottobre). [DA ANDREA: le battute]
|
||||||
poker: {
|
poker: {
|
||||||
type: 'poker',
|
type: 'poker',
|
||||||
names: { player: 'Andrea', cpu: 'Vannino e Pierino' },
|
names: { player: 'Andrea', cpu: 'Vannino e Pierino' },
|
||||||
win: [{ say: 'M\'hai pelato, ragazzo. Nel 1997 un ci si vedeva da queste parti, con quella faccia.', who: 'vannino', pose: 'shrug' }, { set: 'poker_vinto' }],
|
win: [{ say: 'Tu m\'ha pelato. La prossima volta porta il Barone.', who: 'vannino', pose: 'shrug' }, { set: 'poker_vinto' }],
|
||||||
lose: [{ say: 'Le fiches restano al banco. E tu torna quando hai imparato a bluffare.', who: 'pierino_parigi', pose: 'laugh' }],
|
lose: [{ say: 'Le fiches restano al banco. E tu torna quando hai imparato a bluffare.', who: 'pierino_parigi', pose: 'laugh' }],
|
||||||
quit: [{ say: 'Già finito? E il caffè chi lo paga?', who: 'vannino', pose: 'talk' }],
|
quit: [{ say: 'Già finito? E il caffè chi lo paga?', who: 'vannino', pose: 'talk' }],
|
||||||
draw: [{ say: 'Pari. Si rifà domani sera, alla stess\'ora.', who: 'pierino_parigi', pose: 'explain' }],
|
draw: [{ say: 'Pari. Si rifà domani sera, alla stess\'ora.', who: 'pierino_parigi', pose: 'explain' }],
|
||||||
@@ -3336,6 +3356,10 @@ export const story = {
|
|||||||
walk: [[150, 360], [300, 250], [280, 236], [340, 236], [420, 248], [640, 330], [640, 360]],
|
walk: [[150, 360], [300, 250], [280, 236], [340, 236], [420, 248], [640, 330], [640, 360]],
|
||||||
depth: [[236, 0.45], [360, 1.35]],
|
depth: [[236, 0.45], [360, 1.35]],
|
||||||
entry: [400, 352],
|
entry: [400, 352],
|
||||||
|
// Al tramonto, quando la Ghiacciomobile è già un ricordo con la targa, lo zio Mario è nel suo orto (Andrea,
|
||||||
|
// 30 ottobre), e ti aspetta a cena.
|
||||||
|
speakers: { zio_mario: [250, 240] },
|
||||||
|
people: [{ who: 'zio_mario', when: 'indizio_regolo', at: [250, 318], facing: -1, idle: 'stand', talk: ['talk', 'explain', 'point'] }],
|
||||||
hotspots: [
|
hotspots: [
|
||||||
{
|
{
|
||||||
id: 'casa_zio', name: 'casa dello zio Mario', box: [80, 90, 200, 90], at: [260, 290], face: 'left',
|
id: 'casa_zio', name: 'casa dello zio Mario', box: [80, 90, 200, 90], at: [260, 290], face: 'left',
|
||||||
@@ -3355,6 +3379,22 @@ export const story = {
|
|||||||
{
|
{
|
||||||
id: 'indietro', name: 'indietro, verso il ponte delle poste', box: [150, 336, 490, 24], at: [400, 352], exit: { scene: 'ponte_stazione', at: [158, 192], face: 'down' },
|
id: 'indietro', name: 'indietro, verso il ponte delle poste', box: [150, 336, 490, 24], at: [400, 352], exit: { scene: 'ponte_stazione', at: [158, 192], face: 'down' },
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: 'zio_mario', name: 'lo zio Mario', box: [228, 248, 44, 72], at: [300, 330], face: 'left', default: 'talk', when: 'indizio_regolo',
|
||||||
|
actions: {
|
||||||
|
look: [{ say: 'Lo zio Mario nel suo orto, col sole che va giù dietro la casa.' }],
|
||||||
|
// Le battute sono di Andrea (30 ottobre).
|
||||||
|
talk: [
|
||||||
|
{ say: 'Ti s\'aspetta a cena, che c\'è la vitella di maiale.', who: 'zio_mario', pose: 'explain' },
|
||||||
|
{ say: 'Non ti avevo visto, pensavo tu fossi andato all\'estero.' },
|
||||||
|
{ say: 'Io ho girato tanto... il Falcione.', who: 'zio_mario', pose: 'laugh' },
|
||||||
|
{ say: 'Zio, che sei stanco?' },
|
||||||
|
{ say: 'No, dormo!', who: 'zio_mario', pose: 'laugh' },
|
||||||
|
{ say: 'Zio, a me mi garba Michael Jackson!' },
|
||||||
|
{ say: 'Mai col gesso!', who: 'zio_mario', pose: 'laugh' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
// La strada fra il bivio della Provinciale (alle spalle) e la stazione (in fondo); a destra si va al campone delle
|
// La strada fra il bivio della Provinciale (alle spalle) e la stazione (in fondo); a destra si va al campone delle
|
||||||
|
|||||||
+1
-1
@@ -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.54';
|
export const VERSION = '0.1.56';
|
||||||
|
|
||||||
// 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).
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
import test from 'node:test';
|
||||||
|
import assert from 'node:assert/strict';
|
||||||
|
import { existsSync } from 'node:fs';
|
||||||
|
import * as C from '../src/engine/corsa.js';
|
||||||
|
import { story } from '../src/story/story.js';
|
||||||
|
|
||||||
|
const run = (def, until) => { const c = C.newCorsa('x'); while (c.t < until) C.updateCorsa(c, def, 1 / 60); return c; };
|
||||||
|
|
||||||
|
test('la partenza: accelera giù per la strada, il fulmine la prende e sparisce; restano le sgommate', () => {
|
||||||
|
const def = story.closeups.partenza;
|
||||||
|
assert.equal(def.mode, 'parti');
|
||||||
|
for (const src of Object.values(def.frames)) assert.ok(existsSync(src), src);
|
||||||
|
const at = t => C.progress({ t }, def);
|
||||||
|
assert.equal(at(0), 0);
|
||||||
|
assert.ok(at(1.2) > 0 && at(1.6) - at(1.2) > at(1.2) - at(0.8), 'accelera');
|
||||||
|
assert.ok(C.carShown({ t: 2 }, def) && !C.carShown({ t: C.PARTI.bolt + 0.2 }, def));
|
||||||
|
const c = run(def, C.PARTI.bolt + 0.1);
|
||||||
|
assert.ok(c.events.some(e => e.kind === 'corsa-tuono') && c.events.some(e => e.kind === 'corsa-fuoco'));
|
||||||
|
assert.ok(!C.updateCorsa(c, def, 0.01));
|
||||||
|
assert.ok(C.updateCorsa(run(def, C.PARTI.end - 0.01), def, 0.05), 'finita');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('l\'arrivo: il fulmine in fondo, poi viene avanti e ci passa accanto, fuori dal quadro', () => {
|
||||||
|
const def = story.closeups.arrivo;
|
||||||
|
const at = t => C.progress({ t }, def);
|
||||||
|
assert.equal(at(0), 1); assert.equal(at(C.ARRIVA.bolt + C.ARRIVA.run + 0.1), 0);
|
||||||
|
assert.ok(!C.carShown({ t: 0.1 }, def) && C.carShown({ t: 1 }, def));
|
||||||
|
assert.ok(!C.carShown({ t: C.ARRIVA.bolt + C.ARRIVA.run + 0.1 }, def), 'passata');
|
||||||
|
assert.ok(at(1.2) < at(0.8));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('il disegno della corsa non cambia lo stato e usa lo sfondo e i fotogrammi', () => {
|
||||||
|
const calls = [], ctx = new Proxy({}, { get: (o, k) => k in o ? o[k] : (...args) => calls.push([k, ...args]) });
|
||||||
|
const bg = { width: 640, height: 360 }, frames = { dietro: { width: 220, height: 190 }, lampi: { width: 220, height: 190 }, davanti: { width: 220, height: 190 } };
|
||||||
|
for (const [id, t] of [['partenza', 1.4], ['partenza', 3.5], ['arrivo', 1.2], ['arrivo', 2.5]]) {
|
||||||
|
const c = { ...C.newCorsa(id), t }, before = structuredClone(c);
|
||||||
|
calls.length = 0;
|
||||||
|
C.drawCorsa(ctx, c, story.closeups[id], { bg, frames, tint: null });
|
||||||
|
assert.deepEqual(c, before);
|
||||||
|
assert.ok(calls.some(([op, img]) => op === 'drawImage' && img === bg));
|
||||||
|
assert.equal(calls.some(([op, img]) => op === 'drawImage' && Object.values(frames).includes(img)), t < 2.4, 'dopo il fulmine (o passata) la macchina non c\'è');
|
||||||
|
assert.ok(calls.filter(([op]) => op === 'fillRect').length > 20, 'le fiamme');
|
||||||
|
}
|
||||||
|
});
|
||||||
+17
-6
@@ -5,6 +5,18 @@ import { drawPoker, cardAt, HAND } from '../src/engine/poker-render.js';
|
|||||||
import { Game, MINIGAMES, TRIP } from '../src/engine/game.js';
|
import { Game, MINIGAMES, TRIP } from '../src/engine/game.js';
|
||||||
import { story } from '../src/story/story.js';
|
import { story } from '../src/story/story.js';
|
||||||
import { settle } from './helpers.mjs';
|
import { settle } from './helpers.mjs';
|
||||||
|
import { PARTI, ARRIVA } from '../src/engine/corsa.js';
|
||||||
|
|
||||||
|
// I primi piani che vanno da soli (il cruscotto, la partenza, l'arrivo): si lascia scorrere il tempo finché finiscono.
|
||||||
|
function ride(g, seen = []) {
|
||||||
|
for (let t = 0; t < TRIP.end + PARTI.end + ARRIVA.end + 2; t += 0.05) {
|
||||||
|
if (g.closeup && seen.at(-1) !== g.closeup.id) seen.push(g.closeup.id);
|
||||||
|
if (!g.closeup && !g.queue.length && !g.speech) break;
|
||||||
|
if (g.speech) g.skip(); else g.update(0.05);
|
||||||
|
}
|
||||||
|
settle(g);
|
||||||
|
return seen;
|
||||||
|
}
|
||||||
|
|
||||||
const card = s => ({ rank: s.slice(0, -1), suit: { c: 'cuori', q: 'quadri', f: 'fiori', p: 'picche' }[s.at(-1)] });
|
const card = s => ({ rank: s.slice(0, -1), suit: { c: 'cuori', q: 'quadri', f: 'fiori', p: 'picche' }[s.at(-1)] });
|
||||||
const hand = s => s.split(' ').map(card);
|
const hand = s => s.split(' ').map(card);
|
||||||
@@ -71,8 +83,7 @@ test('la macchina del tempo: l\'Arcu la fa comparire, il viaggio porta al Barret
|
|||||||
assert.ok(!g.dialogue, 'finito il discorso, si è pronti a partire');
|
assert.ok(!g.dialogue, 'finito il discorso, si è pronti a partire');
|
||||||
g.act('use', 'macchina_tempo'); settle(g);
|
g.act('use', 'macchina_tempo'); settle(g);
|
||||||
assert.equal(g.closeup?.id, 'viaggio');
|
assert.equal(g.closeup?.id, 'viaggio');
|
||||||
for (let t = 0; t < TRIP.end + 0.5 && g.closeup; t += 0.05) g.update(0.05);
|
assert.deepEqual(ride(g), ['viaggio', 'partenza'], 'il cruscotto, poi la partenza da fuori');
|
||||||
settle(g);
|
|
||||||
assert.equal(g.state.scene, 'barrettino_1997');
|
assert.equal(g.state.scene, 'barrettino_1997');
|
||||||
g.act('talk', 'tavola'); settle(g);
|
g.act('talk', 'tavola'); settle(g);
|
||||||
g.choose(g.options().findIndex(o => o.text.startsWith('C\'è posto'))); settle(g);
|
g.choose(g.options().findIndex(o => o.text.startsWith('C\'è posto'))); settle(g);
|
||||||
@@ -82,7 +93,8 @@ test('la macchina del tempo: l\'Arcu la fa comparire, il viaggio porta al Barret
|
|||||||
g.closeupClose(); settle(g);
|
g.closeupClose(); settle(g);
|
||||||
assert.ok(g.state.flags.poker_vinto);
|
assert.ok(g.state.flags.poker_vinto);
|
||||||
assert.ok(g.hotspot('arcu'), 'l\'Arcu è venuto anche lui');
|
assert.ok(g.hotspot('arcu'), 'l\'Arcu è venuto anche lui');
|
||||||
g.act('walk', 'porta'); settle(g);
|
g.act('walk', 'porta');
|
||||||
|
assert.deepEqual(ride(g), ['arrivo'], 'al ritorno, l\'arrivo col fulmine');
|
||||||
assert.equal(g.state.scene, 'via_liguri_magelli');
|
assert.equal(g.state.scene, 'via_liguri_magelli');
|
||||||
assert.ok(!g.state.flags.macchina_trappola && !g.hotspot('macchina_tempo'), 'tornati, la macchina sparisce');
|
assert.ok(!g.state.flags.macchina_trappola && !g.hotspot('macchina_tempo'), 'tornati, la macchina sparisce');
|
||||||
assert.equal(g.goBack(), false, 'nel 2007 il pulsante non c\'è');
|
assert.equal(g.goBack(), false, 'nel 2007 il pulsante non c\'è');
|
||||||
@@ -91,11 +103,10 @@ test('la macchina del tempo: l\'Arcu la fa comparire, il viaggio porta al Barret
|
|||||||
g.choose(g.options().findIndex(o => o.text.startsWith('Bei tempi'))); settle(g);
|
g.choose(g.options().findIndex(o => o.text.startsWith('Bei tempi'))); settle(g);
|
||||||
assert.ok(!g.dialogue, 'finito il discorso, si è pronti a partire');
|
assert.ok(!g.dialogue, 'finito il discorso, si è pronti a partire');
|
||||||
g.act('use', 'macchina_tempo'); settle(g);
|
g.act('use', 'macchina_tempo'); settle(g);
|
||||||
for (let t = 0; t < TRIP.end + 0.5 && g.closeup; t += 0.05) g.update(0.05);
|
ride(g);
|
||||||
settle(g);
|
|
||||||
assert.equal(g.state.scene, 'barrettino_1997');
|
assert.equal(g.state.scene, 'barrettino_1997');
|
||||||
assert.equal(g.scene.back.label, 'Torna al 2007');
|
assert.equal(g.scene.back.label, 'Torna al 2007');
|
||||||
assert.ok(g.goBack()); settle(g);
|
assert.ok(g.goBack()); ride(g);
|
||||||
assert.equal(g.state.scene, 'via_liguri_magelli');
|
assert.equal(g.state.scene, 'via_liguri_magelli');
|
||||||
assert.ok(!g.hotspot('macchina_tempo'));
|
assert.ok(!g.hotspot('macchina_tempo'));
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -75,3 +75,17 @@ test('Via Liguri Magelli: prima la Ghiacciomobile nel muro (senza targa), dal tr
|
|||||||
assert.ok(g.hotspot('targa') && !g.hotspot('ghiacciomobile'));
|
assert.ok(g.hotspot('targa') && !g.hotspot('ghiacciomobile'));
|
||||||
assert.ok(existsSync(new URL('../assets/scenes/via-liguri-magelli-muro.png', import.meta.url)));
|
assert.ok(existsSync(new URL('../assets/scenes/via-liguri-magelli-muro.png', import.meta.url)));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('lo zio Mario: davanti alla Ghiacciomobile fino al tramonto, poi nel suo orto', () => {
|
||||||
|
const g = new Game(story);
|
||||||
|
g.go('via_liguri_magelli'); settle(g);
|
||||||
|
assert.ok(g.hotspot('zio_mario'));
|
||||||
|
g.go('orti_zio_mario'); settle(g);
|
||||||
|
assert.ok(!g.hotspot('zio_mario'));
|
||||||
|
g.state.flags.indizio_regolo = true;
|
||||||
|
assert.ok(g.hotspot('zio_mario'));
|
||||||
|
assert.ok(inside(story.scenes.orti_zio_mario.walk, g.hotspot('zio_mario').at));
|
||||||
|
g.act('talk', 'zio_mario'); settle(g);
|
||||||
|
g.go('via_liguri_magelli'); settle(g);
|
||||||
|
assert.ok(!g.hotspot('zio_mario'));
|
||||||
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user