Compare commits

..
4 Commits
12 changed files with 27 additions and 17 deletions
Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.7 KiB

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 28 KiB

+4 -3
View File
@@ -256,10 +256,11 @@ I prompt fissi (stile, scene, foglio sprite) sono in `prompts/STILE.md`, escluso
`assets/closeups/gp-fortezza.png` (prompt `prompts/closeups/gp-fortezza.txt`, guida dalla planimetria
`assets/raw/fortezza-planimetria.png`, satellite in `assets/raw/fortezza-satellite.png`); il tracciato è ricalcato
sulla strada dipinta. Disegno `gara-render.js`, test `tests/gara.test.mjs`. I piloti sono dati in
`src/story/piloti.js`: una riga per amico, `motore` e `testa` da 1 a 5, colori dalle foto. Corrono Puntella (SR,
colori Aprilia da GP provvisori), Cistola (CR 50 Z), Andrea (Malaguti Fifty rosso e nero), Tozzino (Booster blu
`src/story/piloti.js`: una riga per amico, `motore` e `testa` da 1 a 5, colori dalle foto. Corrono Puntella (SR
truccatissimo, motore 6, viola e giallo dalla sua foto, ritratto di Codex, testa «non pervenuta»), il Porno (Andrea
Bini, consenso del 28 ottobre: Italjet Formula giallo, motore 5, ritratto di Codex), Cistola (CR 50 Z), Andrea (Malaguti Fifty rosso e nero), Tozzino (Booster blu
scuro, di serie, casco alla Damon Hill di Codex: `prompts/personaggi/casco-tozzino.txt`), l'Arcu (Betino). Col telefono
si guida con un dito: premuto è gas, lo swipe indica dove andare sullo schermo (Codex, 28 ottobre). **Puntella (Marco Villani) non corre finché manca il suo consenso** (`consenso: null` in piloti.js: quando arriva, la data). Mancano: quanto erano
si guida con un dito: premuto è gas, lo swipe indica dove andare sullo schermo (Codex, 28 ottobre). Puntella (Marco Villani) ha dato il consenso il 28 ottobre; chi ha `consenso: null` in piloti.js non corre. Mancano: quanto erano
truccati gli altri, le battute di Andrea, il rumore del motore (c'è solo
quello dell'arrivo in griglia); i confini della paglia non si vedono sul quadro (revisione di Codex, punto 9).
- Strade attorno a casa (Andrea, 28 ottobre): la scena `area_camper` ora si chiama «Le villette del Giannini» (ci abita
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "leggenda-del-regolo",
"version": "0.1.33",
"version": "0.1.35",
"private": true,
"type": "module",
"scripts": {
+3 -1
View File
@@ -174,7 +174,9 @@ function card(ctx, c, look, sheet) {
for (const [k, [label, value]] of [['MOTORE', r.motore], ['TESTA', r.testa]].entries()) {
const yy = y + 116 + k * 12;
text(ctx, label, x + 222, yy, 5, '#c5c6b6');
for (let i = 0; i < 5; i++) { ctx.fillStyle = i < value ? (k ? '#b9d392' : '#e0583a') : '#3a3f3c'; ctx.fillRect(x + 262 + i * 13, yy - 3, 10, 6); }
// Cinque caselle; il motore truccatissimo (6) ne accende una sesta, gialla. Per qualcuno la testa è una scritta.
if (k && r.testaNota) { text(ctx, r.testaNota, x + 262, yy, 5, '#e0583a'); continue; }
for (let i = 0; i < Math.max(5, value); i++) { ctx.fillStyle = i >= 5 ? '#ffe28a' : i < value ? (k ? '#b9d392' : '#e0583a') : '#3a3f3c'; ctx.fillRect(x + 262 + i * 12, yy - 3, 9, 6); }
}
text(ctx, 'TOCCA: IL PROSSIMO', x + w / 2, y + h - 6, 5, '#8f9488', 'center');
}
+3 -2
View File
@@ -35,10 +35,11 @@ const clamp = (v, lo, hi) => Math.max(lo, Math.min(hi, v));
const wrapAngle = a => Math.atan2(Math.sin(a), Math.cos(a));
// I piloti sono dati (story.closeups.gara.riders, da piloti.js): `motore` da 1 (di serie) a 5 (truccato da far
// paura), `testa` da 1 (matto) a 5 (prudente). Ne vengono velocità massima e accelerazione in px/s, tenuta, e per gli
// paura, 6 truccatissimo), `testa` da 1 (matto) a 5 (prudente). Ne vengono velocità massima e accelerazione in px/s, tenuta, e per gli
// altri quanto si fidano delle curve (`caution`) e quanto spesso rischiano troppo (`slip`).
export function rider({ motore = 3, testa = 3, ...r }) {
const m = clamp(motore, 1, 5), t = clamp(testa, 1, 5);
// Il 6 è il truccatissimo: lo SR di Puntella (Andrea, 28 ottobre).
const m = clamp(motore, 1, 6), t = clamp(testa, 1, 5);
return { ...r, motore: m, testa: t, vmax: 74 + 6.5 * m, accel: 40 + 5 * m, grip: 1.1 - 0.03 * m, caution: 1.0025 - 0.0125 * t, slip: 0.4275 - 0.0775 * t };
}
// Il gruppo di prova, quando la storia non ne dà uno.
+11 -6
View File
@@ -1,21 +1,26 @@
// La gara dei cinquantini (idea di Andrea, 28 ottobre): chi corre, in ordine di griglia (due per fila).
// Ogni amico che manda la foto del suo motorino si aggiunge con una riga. `motore`: da 1 (di serie) a 5 (truccato da
// far paura); `testa`: da 1 (matto, in curva rischia) a 5 (prudente). `color` e `trim`: i colori del motorino in pista.
// far paura; 6 truccatissimo, solo lo SR di Puntella); `testa`: da 1 (matto, in curva rischia) a 5 (prudente). `color` e `trim`: i colori del motorino in pista.
// Per la presentazione: `moto`, il disegno del motorino (Codex, dalla foto); `sprite`, il personaggio del gioco (un
// nome di story.characters), oppure `face`, un ritratto quadrato; senza nessuno dei due, una sagoma. `casco`: il disegno
// del casco per il cartellino, `helmet` e `stripe` i suoi colori visti dall'alto in pista.
// del casco per il cartellino, `helmet` e `stripe` i suoi colori visti dall'alto in pista. `testaNota`: una scritta al
// posto delle caselle della testa.
// Persone vere solo col loro consenso (`consenso`: chi l'ha dato e quando).
export const piloti = [
// Lo SR di Puntella era il più truccato di tutti; per ora i colori dell'Aprilia SR 50 da GP (foto di Andrea).
{ id: 'puntella', name: 'Puntella', bike: 'lo SR', motore: 5, testa: 1, color: '#5a3fb5', trim: '#e8442e', moto: 'assets/closeups/gp/sr.png', consenso: null }, // [DA ANDREA: consenso di Marco Villani]
// Puntella (Marco Villani, consenso del 28 ottobre) con lo SR truccatissimo, viola e giallo come il suo (foto di
// Andrea); il ritratto dalla sua foto.
{ id: 'puntella', name: 'Puntella', bike: 'lo SR truccatissimo', motore: 6, testa: 1, testaNota: 'NON PERVENUTA', color: '#5b2a9e', trim: '#f2c81e', moto: 'assets/closeups/gp/sr.png', face: 'assets/closeups/gp/puntella.png', consenso: '2026-10-28' },
// Cistola (Davide Poggi) col suo CR 50 Z, blu notte e argento, dalla foto che ha mandato; il volto dal suo murale.
{ id: 'cistola', name: 'Cistola', bike: 'il CR 50 Z', motore: 4, testa: 3, color: '#1d2440', trim: '#a9adb5', moto: 'assets/closeups/gp/cr50z.png', face: 'assets/closeups/gp/cistola.png', consenso: '2026-10-27' },
// Il Malaguti Fifty di Andrea: rosso con le rifiniture nere.
{ id: 'andrea', name: 'Andrea', bike: 'il Fifty', motore: 3, testa: 3, color: '#d8402f', trim: '#1c1c1c', moto: 'assets/closeups/gp/fifty.png', sprite: 'andrea' },
// Il Porno (Andrea Bini, consenso del 28 ottobre) col suo Italjet Formula giallo, che va fortissimo (foto di Andrea);
// il ritratto dalla sua foto.
{ id: 'porno', name: 'Il Porno', bike: 'il Formula', motore: 5, testa: 3, color: '#f2c81e', trim: '#2a2a2e', moto: 'assets/closeups/gp/formula.png', face: 'assets/closeups/gp/porno.png', consenso: '2026-10-28' },
// Tozzino (Francesco Tozzi) col suo Booster blu scuro, di serie, dalle foto che ha mandato (l'adesivo sul manubrio compreso).
{ id: 'tozzino', name: 'Tozzino', bike: 'il Booster', motore: 1, testa: 3, color: '#1a2a52', trim: '#111318', moto: 'assets/closeups/gp/booster.png', sprite: 'tozzino',
// Il casco alla Damon Hill: blu scuro con le righe bianche dei remi (Andrea, 28 ottobre).
casco: 'assets/closeups/gp/casco-tozzino.png', helmet: '#1b2a5c', stripe: '#f4f4f4' },
// Il casco alla Damon Hill: blu notte con poche pale di remo bianche, strette e a punta (foto di Andrea, 28 ottobre).
casco: 'assets/closeups/gp/casco-tozzino.png', helmet: '#131c3c', stripe: '#f4f4f4' },
// Il Betino dell'Arcu: verde e crema, lento ma non cade mai.
{ id: 'arcu', name: 'L\'Arcu', bike: 'il Betino', motore: 1, testa: 5, color: '#2f7a3a', trim: '#e8d9a0', moto: 'assets/closeups/gp/betino.png', sprite: 'arcu' },
];
+1 -1
View File
@@ -1,5 +1,5 @@
// La versione del gioco: la cambia scripts/bump.sh, insieme a package.json.
export const VERSION = '0.1.33';
export const VERSION = '0.1.35';
// 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).
+4 -3
View File
@@ -39,11 +39,12 @@ const careful = c => {
return c.holding;
};
test('i piloti sono dati: motore e testa da 1 a 5 danno velocità, accelerazione e prudenza', () => {
test('i piloti sono dati: motore da 1 a 6 e testa da 1 a 5 danno velocità, accelerazione e prudenza', () => {
const slow = rider({ motore: 1, testa: 5 }), fast = rider({ motore: 5, testa: 1 });
assert.ok(fast.vmax > slow.vmax && fast.accel > slow.accel && fast.grip < slow.grip);
assert.ok(fast.slip > slow.slip && fast.caution > slow.caution);
assert.deepEqual(rider({ motore: 9, testa: -2 }).motore, 5, 'fuori scala si ferma ai bordi');
assert.deepEqual(rider({ motore: 9, testa: -2 }).motore, 6, 'fuori scala si ferma ai bordi (6, il truccatissimo)');
assert.equal(rider({ motore: 9, testa: -2 }).testa, 1);
// Ogni pilota della storia ha nome, motorino e colore; Andrea c'è una volta sola.
for (const p of piloti) { assert.ok(p.id && p.name && p.bike && /^#[0-9a-f]{6}$/i.test(p.color), p.id); }
assert.equal(piloti.filter(p => p.id === 'andrea').length, 1);
@@ -250,7 +251,7 @@ test('nella storia: dal Trappola l\'Arcu scherza sul Betino, poi la sfida; prima
assert.ok(before.some(t => t.includes('prendo la rincorsa')));
assert.equal(g.closeup?.id, 'gara'); assert.equal(g.closeup.level, 'seria');
assert.deepEqual(g.closeup.riders.map(r => r.id), piloti.filter(p => p.consenso !== null).map(p => p.id));
assert.ok(!g.closeup.riders.some(r => r.id === 'puntella'), 'senza consenso non corre');
assert.ok(!g.closeup.riders.some(r => r.consenso === null), 'senza consenso non corre');
g.closeup.result = { winner: 'player', place: 1, times: {}, order: ['andrea'], offs: 0 }; g.closeup.step = 'result';
g.closeupClose(); const after = settle(g).map(s => s.text);
assert.ok(g.state.flags.gara_vinta);