Il flipper rifatto da Codex: tavola ad alta risoluzione con lacca, cromature e luci animate; due LOCK (tre passaggi sulla stessa rampa in venti secondi, Fortezza e Trebbio), la SUPER SPECIAL al centro che si apre con entrambi i lock e dà pallina premio e multiball a tre; jackpot fino a x3 coi bersagli, nuove fanfare; la valvola contro il rientro nella molla; display del punteggio e pannello della caccia al jackpot ai lati; test unitari e nel browser (lock, super, multiball) (Andrea)
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GiECd9RWGMKV7n3K1mdy8T
This commit is contained in:
@@ -29,6 +29,7 @@ try {
|
||||
// Aspetta che finisca la dissolvenza d'ingresso: le immagini devono mostrare i colori della tavola.
|
||||
const readyAt = await page.evaluate(() => game.closeup.visual.time);
|
||||
await page.waitForFunction(t => game.closeup.visual.time > t + 1, readyAt);
|
||||
assert.equal(await page.locator('#scene').getAttribute('width'), '1280', 'il flipper usa la risoluzione doppia');
|
||||
assert.equal(await page.locator('#bocce-throw').textContent(), 'Lancia');
|
||||
assert.ok(await page.locator('#flipper-help').isVisible());
|
||||
assert.equal(await page.locator('#bocce-left').textContent(), '← Flipper');
|
||||
@@ -96,13 +97,51 @@ try {
|
||||
assert.deepEqual(reward, { balls: 2, step: 'play', winner: 'player' });
|
||||
await page.waitForFunction(() => document.querySelector('#bocce-status').textContent.includes('pallina premio vinta'));
|
||||
await page.screenshot({ path: `${out}/${name}-premio.png` });
|
||||
// Una sequenza reale di rampe, con il motore: primo lock, secondo lock, rampa centrale e tre palline.
|
||||
await page.evaluate(async () => {
|
||||
const m = await import('/src/engine/flipper.js');
|
||||
Object.assign(game.closeup, m.newFlipper(73, { level: 'bona' }));
|
||||
window.pinballShot = id => {
|
||||
const c = game.closeup, r = c.ramps.find(r => r.id === id);
|
||||
if (m.waiting(c)) m.launch(c, 0.8);
|
||||
Object.assign(c.ball, { x: r.path[0][0], y: r.mouth[0][1] + 14, vx: 0, vy: -470, ramp: null });
|
||||
let entered = false;
|
||||
for (let i = 0; i < 1000; i++) { m.update(c, m.STEP); if (c.ball?.ramp) entered = true; else if (entered) return; }
|
||||
throw new Error(`rampa ${id} non completata`);
|
||||
};
|
||||
for (let i = 0; i < 3; i++) window.pinballShot('sinistra');
|
||||
});
|
||||
assert.equal(await page.evaluate(() => game.closeup.locks.length), 1);
|
||||
await page.screenshot({ path: `${out}/${name}-lock.png` });
|
||||
await page.evaluate(async () => {
|
||||
for (let i = 0; i < 3; i++) window.pinballShot('destra');
|
||||
const m = await import('/src/engine/flipper.js');
|
||||
for (let i = 0; i < 4; i++) m.update(game.closeup, 0.2);
|
||||
});
|
||||
assert.equal(await page.evaluate(() => game.closeup.special), 'super');
|
||||
await page.screenshot({ path: `${out}/${name}-super.png` });
|
||||
const multi = await page.evaluate(async () => {
|
||||
window.pinballShot('super');
|
||||
const m = await import('/src/engine/flipper.js'); m.update(game.closeup, 0.25); m.update(game.closeup, 0.25);
|
||||
// Ferma solo la simulazione per fotografare le tre palline, prima che una possa scendere.
|
||||
window.pinballResume = game.update.bind(game); game.update = dt => { game.closeup.visual.time += dt; };
|
||||
return { balls: m.activeBalls(game.closeup).length, locks: game.closeup.locks.length, reserve: game.closeup.balls, time: game.closeup.visual.time };
|
||||
});
|
||||
assert.deepEqual({ balls: multi.balls, locks: multi.locks, reserve: multi.reserve }, { balls: 3, locks: 0, reserve: 5 });
|
||||
await page.waitForFunction(t => game.closeup.visual.time > t + 0.7, multi.time);
|
||||
await page.screenshot({ path: `${out}/${name}-multiball.png` });
|
||||
const frameMs = await page.evaluate(() => new Promise(resolve => {
|
||||
const stamps = []; const tick = t => { stamps.push(t); if (stamps.length === 20) resolve((t - stamps[0]) / 19); else requestAnimationFrame(tick); }; requestAnimationFrame(tick);
|
||||
}));
|
||||
console.log(`${name}: intervallo frame medio ${frameMs.toFixed(1)} ms`);
|
||||
await page.evaluate(() => { game.update = window.pinballResume; delete window.pinballResume; delete window.pinballShot; });
|
||||
// Si consumano le palline rimaste, compresa quella vinta, per arrivare al risultato reale.
|
||||
const finalScore = await page.evaluate(async () => {
|
||||
const m = await import('/src/engine/flipper.js'), c = game.closeup;
|
||||
for (let i = 0; i < 4 && c.step === 'play'; i++) {
|
||||
for (let i = 0; i < 12 && c.step === 'play'; i++) {
|
||||
if (m.waiting(c)) m.launch(c, 0.8);
|
||||
c.saveUntil = 0;
|
||||
Object.assign(c.ball, { x: 320, y: 342, vx: 0, vy: 300, ramp: null }); m.update(c, 0.1);
|
||||
for (const ball of m.activeBalls(c)) Object.assign(ball, { x: 320, y: 348, vx: 0, vy: 300, ramp: null, releaseAt: 0 }); m.update(c, 0.1);
|
||||
}
|
||||
return c.score;
|
||||
});
|
||||
@@ -111,6 +150,7 @@ try {
|
||||
await page.screenshot({ path: `${out}/${name}-fine.png` });
|
||||
if (mobile) await page.locator('#closeup-close').click(); else await page.keyboard.press('Enter'); // Invio chiude il risultato
|
||||
await page.waitForFunction(() => game.state.flags.flipper_vinto && !game.closeup);
|
||||
await page.waitForFunction(() => document.querySelector('#scene').width === 640);
|
||||
await page.close();
|
||||
}
|
||||
assert.deepEqual(errors, []);
|
||||
|
||||
Reference in New Issue
Block a user