fertig-classic-games/__jig_random_test.html

105 lines
4.4 KiB
HTML

<!doctype html>
<html><head><meta charset="utf-8">
<script type="importmap">{"imports":{"phaser":"/phaser.esm.js"}}</script>
<style>html,body{margin:0;background:#111}canvas{display:block}</style>
</head><body>
<div id="log"></div>
<script type="module">
import * as Phaser from 'phaser';
import JigsawGame from './src/games/jigsaw/JigsawGame.js';
const log = (m) => { document.getElementById('log').textContent += m + '\n'; console.log('[t]', m); };
let failures = 0;
const check = (ok, msg) => { if (!ok) { failures++; log('FAIL: ' + msg); } else log('ok: ' + msg); };
const wait = (ms) => new Promise((r) => setTimeout(r, ms));
window.addEventListener('error', (e) => log('PAGE ERROR: ' + e.message));
window.addEventListener('unhandledrejection', (e) => log('PAGE REJECTION: ' + (e.reason && e.reason.stack || e.reason)));
const ART = [
{ name: 'Alien World', path: 'assets/images/shift/alien-world.png' },
{ name: 'Aquaroom', path: 'assets/images/shift/aquaroom.png' },
{ name: 'Aztec Warrior', path: 'assets/images/shift/aztec-warrior.png' },
{ name: 'Cat On Tiger', path: 'assets/images/shift/cat-on-tiger.png' },
{ name: 'Cockpit', path: 'assets/images/shift/cockpit.png' },
];
const config = {
type: Phaser.AUTO,
width: 1920, height: 1080,
parent: document.body,
backgroundColor: '#000',
scene: [ { key: 'boot', create() {
this.cache.json.add('shift-artwork', { artwork: ART });
this.cache.json.add('music', { tracks: [] });
this.scene.start('jigsaw-game');
} }, JigsawGame ],
};
const game = new Phaser.Game(config);
const s = () => game.scene.getScene('jigsaw-game');
async function waitForState(st, tries = 200) {
for (let i = 0; i < tries; i++) { if (s().state === st) return true; await wait(25); }
return false;
}
async function main() {
for (let i = 0; i < 400 && !s(); i++) await wait(50); // boot → jigsaw start is async
if (!s()) throw new Error('jigsaw scene never started');
for (let i = 0; i < 400 && !s().menu; i++) await wait(50);
check(!!s().menu, 'menu built');
const btn = s().randomStartButton;
check(!!btn, 'randomStartButton exists');
check(btn.visible === true && s().menu.visible === true, 'randomStartButton visible inside menu');
const cy = 1080 / 2 + 12;
const panelBottom = cy + 445; // panel H = 890
check(btn.y + btn.options.height / 2 <= panelBottom, `button bottom (${(btn.y + btn.options.height / 2).toFixed(0)}) inside panel (${panelBottom})`);
check(btn.y - btn.options.height / 2 > s().startButton.y + s().startButton.options.height / 2 + 8, 'button sits below Start with a gap');
// 8 one-click random starts from the menu
s().selectedDiff = 'easy';
const names = new Set();
let allPlaying = true, allPieces = true, nameValid = true;
for (let i = 0; i < 8; i++) {
s().toMenu();
await wait(30);
s().startRandomPuzzle();
const ok = await waitForState('playing');
if (i % 5 === 0) log(` (start #${i}: state=${s().state}, img=${s().imageName || '-'})`);
if (!ok) { allPlaying = false; log(` (start #${i}: state=${s().state})`); continue; }
if (s().pieces.length !== 25) allPieces = false;
names.add(s().imageName);
if (!ART.some((a) => a.name === s().imageName)) nameValid = false;
}
check(allPlaying, 'state=playing after every startRandomPuzzle call');
check(allPieces, '25 pieces built on every random start');
check(nameValid, 'started image is always a valid artwork entry');
check(names.size >= 2, `randomness: ${names.size}/5 distinct images in 8 starts (${[...names].join(', ')})`);
// Single-image guard: no infinite loop, still starts with the only image.
s().toMenu();
s().artwork = [ART[0]]; s().imageIndex = 0;
s().startRandomPuzzle();
await waitForState('playing');
check(s().state === 'playing' && s().imageName === 'Alien World', 'single-image artwork: starts with the only image');
// Difficulty must be preserved by a random start.
s().toMenu();
s().artwork = ART; s().imageIndex = 0;
s().selectDifficulty('medium');
s().startRandomPuzzle();
await waitForState('playing');
check(s().state === 'playing' && s().total === 36 && s().difficulty === 'medium', 'random start keeps the selected difficulty (36 pieces)');
log(failures === 0 ? 'ALL PASS' : failures + ' FAILURES');
document.title = failures === 0 ? 'PASS' : 'FAIL:' + failures;
}
main().catch((e) => {
log('ERROR: ' + ((e && e.stack) || e));
failures++;
document.title = 'FAIL:error';
});
</script>
</body></html>