Il flipper del River: la tavola di Codex con San Piero dipinto (Fortezza, Pieve, torre, la Sieve fra i flipper, il Regolo con la corona, le bandiere dei rioni) e sopra le parti meccaniche del gioco: molla, arco, corsie dei rioni (tutte e quattro: PALIO), funghi, bersagli a caduta, Regolo, sponde elastiche, due flipper; fisica a passo fisso, tre palline, tre livelli (Andrea)
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GiECd9RWGMKV7n3K1mdy8T
This commit is contained in:
@@ -0,0 +1,72 @@
|
||||
// Il flipper del River nel browser vero: dal bar, la molla col mouse e col dito, i flipper coi pulsanti e con le
|
||||
// frecce, il risultato. npm run browser:flipper — schermate in /tmp/regolo-flipper.
|
||||
import { chromium } from 'playwright';
|
||||
import { mkdirSync } from 'node:fs';
|
||||
import assert from 'node:assert/strict';
|
||||
import { staticServer } from './helpers.mjs';
|
||||
|
||||
const out = process.env.OUT ?? '/tmp/regolo-flipper';
|
||||
mkdirSync(out, { recursive: true });
|
||||
const server = await staticServer();
|
||||
let browser;
|
||||
const errors = [];
|
||||
try {
|
||||
browser = await chromium.launch({ args: ['--autoplay-policy=no-user-gesture-required', '--use-gl=angle', '--use-angle=swiftshader', '--enable-unsafe-swiftshader'] });
|
||||
for (const [name, mobile, viewport] of [['desktop', false, { width: 1280, height: 860 }], ['touch', true, { width: 844, height: 390 }]]) {
|
||||
const page = await browser.newPage({ viewport, hasTouch: mobile, isMobile: mobile });
|
||||
page.on('pageerror', e => errors.push(e.message));
|
||||
await page.goto(`http://127.0.0.1:${server.port}/`);
|
||||
await page.click('#splash'); await page.click('#new-game'); await page.click('#rione [data-rione="campomigliaio"]'); await page.click('#skip-intro');
|
||||
await page.evaluate(async () => {
|
||||
const { settle } = await import('/tests/helpers.mjs');
|
||||
settle(game); game.go('via_provinciale'); settle(game);
|
||||
game.act('use', 'river'); settle(game);
|
||||
game.choose(game.options().findIndex(o => o.text.startsWith('Una partita alla bona'))); settle(game);
|
||||
});
|
||||
await page.waitForSelector('#bocce-controls:not([hidden])');
|
||||
await page.waitForFunction(async () => (await import('/src/engine/render.js')).hasBackground('assets/closeups/river-flipper.png'));
|
||||
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');
|
||||
await page.screenshot({ path: `${out}/${name}-tavola.png` });
|
||||
const box = await page.locator('#scene').boundingBox(), P = (x, y) => [box.x + x / 640 * box.width, box.y + y / 360 * box.height];
|
||||
// La molla: col mouse tenendo premuto sulla scena, col dito il pulsante Lancia.
|
||||
if (mobile) await page.locator('#bocce-throw').tap();
|
||||
else {
|
||||
await page.mouse.move(...P(440, 320)); await page.mouse.down();
|
||||
await page.waitForFunction(() => game.closeup.holding && game.closeup.power > 0.3, null, { polling: 'raf' });
|
||||
await page.mouse.up();
|
||||
}
|
||||
await page.waitForFunction(() => game.closeup && !game.closeup.ball?.waiting, null, { timeout: 5000 });
|
||||
// I flipper: col dito i pulsanti tenuti premuti, col mouse la metà della scena e poi le frecce.
|
||||
if (mobile) {
|
||||
const b = await page.locator('#bocce-left').boundingBox();
|
||||
const cdp = await page.context().newCDPSession(page);
|
||||
await cdp.send('Input.dispatchTouchEvent', { type: 'touchStart', touchPoints: [{ x: b.x + b.width / 2, y: b.y + b.height / 2 }] });
|
||||
await page.waitForFunction(() => game.closeup.flippers.left.held.length > 0);
|
||||
await page.screenshot({ path: `${out}/${name}-flipper.png` });
|
||||
await cdp.send('Input.dispatchTouchEvent', { type: 'touchEnd', touchPoints: [] });
|
||||
await page.waitForFunction(() => game.closeup.flippers.left.held.length === 0);
|
||||
} else {
|
||||
await page.mouse.move(...P(400, 200)); await page.mouse.down();
|
||||
await page.waitForFunction(() => game.closeup.flippers.right.held.length > 0);
|
||||
await page.screenshot({ path: `${out}/${name}-flipper.png` });
|
||||
await page.mouse.up();
|
||||
await page.waitForFunction(() => game.closeup.flippers.right.held.length === 0);
|
||||
await page.keyboard.down('ArrowLeft');
|
||||
await page.waitForFunction(() => game.closeup.flippers.left.held.length > 0);
|
||||
await page.keyboard.up('ArrowLeft');
|
||||
await page.waitForFunction(() => game.closeup.flippers.left.held.length === 0);
|
||||
}
|
||||
// La fine: si fa finire la partita e si guarda il quadro.
|
||||
await page.evaluate(() => { const c = game.closeup; c.step = 'result'; c.ball = null; c.result = { winner: 'player', score: 7350, goal: c.skill.goal }; });
|
||||
await page.waitForFunction(() => document.querySelector('#bocce-throw').textContent === 'Finita');
|
||||
assert.match(await page.locator('#bocce-status').textContent(), /7350 punti/);
|
||||
await page.screenshot({ path: `${out}/${name}-fine.png` });
|
||||
await page.locator('#closeup-close').click();
|
||||
await page.waitForFunction(() => game.state.flags.flipper_vinto);
|
||||
await page.close();
|
||||
}
|
||||
assert.deepEqual(errors, []);
|
||||
console.log(`ok: schermate in ${out}`);
|
||||
} finally { await browser?.close(); server.kill(); }
|
||||
Reference in New Issue
Block a user