Flipper più ricco (Codex): skill shot da 25.000 sulla corsia lampeggiante, spinner RIVER da 500 a giro, salvataggi laterali conquistabili, bonus a fine pallina fino a ×5; spintarella con N, freccia su o SCUOTI (terza scossa: TILT, palette spente e bonus perso); il Regolo del futuro concede 30 secondi per il colpo finale da 500.000; fuochi, fanfare, knocker, ruggito e conto alla rovescia

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GiECdB3MK67QCXQMfaP2cV
This commit is contained in:
2026-11-02 11:04:26 +01:00
co-authored by Claude Opus 5.5
parent 650d4e9cf8
commit 4b5408597f
8 changed files with 395 additions and 26 deletions
+30
View File
@@ -132,6 +132,36 @@ try {
await page.keyboard.up('ShiftRight'); await page.keyboard.up('ShiftLeft');
await page.waitForFunction(() => !game.closeup.flippers.left.held.length && !game.closeup.flippers.right.held.length);
}
// Nuove regole sul canvas reale: skill shot, fuochi e SCUOTI anche senza pulsantiera.
await page.evaluate(async () => {
const m = await import('/src/engine/flipper.js');
window.showState = structuredClone(game.closeup); window.showUpdate = game.update; game.update = () => {};
const c = game.closeup; Object.assign(c, m.newFlipper(1, { level: c.level })); m.launch(c, 0.3);
Object.assign(c.ball, { x: c.lanes[c.skillShot.lane].x, y: 103, vx: 0, vy: 300 }); m.update(c, m.STEP);
if (!c.events.some(e => e.kind === 'flipper-skill')) throw new Error('skill shot non premiato');
c.ball.waiting = true; c.kickback.left = true; c.spinner.speed = 30;
for (let i = 0; i < 3; i++) m.update(c, 0.25);
Object.assign(c.ball, { waiting: false, x: 320, y: 250, vx: 0, vy: 0 });
// Anche a simulazione ferma, lascia finire il conteggio animato del display.
(await import('/src/engine/render.js')).render(document.querySelector('#scene').getContext('2d'), game, { time: performance.now() });
c.visual.time += 0.6;
});
await page.screenshot({ path: `${out}/${name}-fuochi.png` });
for (let i = 1; i <= 3; i++) {
await page.evaluate(() => { game.closeup.sim += 1; game.closeup.ball.releaseAt = 0; });
if (mobile) {
const b = await page.locator('#scene').boundingBox();
await touch('touchStart', [[b.x + b.width / 2, b.y + b.height * 347 / 360]]); await touch('touchEnd', []);
} else await page.keyboard.press('n');
assert.equal(await page.evaluate(() => game.closeup.tilt.warnings), i);
}
assert.equal(await page.evaluate(() => game.closeup.tilt.active), true);
await page.keyboard.down('ArrowLeft');
assert.equal(await page.evaluate(() => game.closeup.flippers.left.held.length), 0);
await page.keyboard.up('ArrowLeft');
await page.screenshot({ path: `${out}/${name}-tilt.png` });
await page.evaluate(() => { Object.assign(game.closeup, window.showState); game.update = window.showUpdate; delete window.showState; delete window.showUpdate; });
assert.deepEqual(errors, [], 'nessun errore durante skill shot e tilt');
// Il traguardo aggiunge una pallina e lascia continuare la partita.
const reward = await page.evaluate(async () => {
const m = await import('/src/engine/flipper.js'), c = game.closeup;