Files
games/crates/apps/game-snake-poc-tauri/frontend/ts/main.ts
2026-09-21 01:13:37 +02:00

68 lines
2.8 KiB
TypeScript

// file: crates/apps/game-snake-poc-tauri/frontend/ts/main.ts
// version: 2
import "../css/main.css";
import { loadSnakeTauriAssets } from "./assets";
import { getRuntimeDescriptor, reportFrontendReady } from "./bridge";
import { startGame } from "./game";
import { bindInputs } from "./input";
import { frontendError, frontendInfo, initializeFrontendTracing } from "./logging";
function requiredElement<T extends HTMLElement>(identifier: string): T {
const element = document.getElementById(identifier);
if (element === null) {
throw new Error(`Élément frontend requis absent : ${identifier}`);
}
return element as T;
}
async function bootstrap(): Promise<void> {
await initializeFrontendTracing();
frontendInfo("Snake Tauri frontend bootstrap started");
const descriptor = await getRuntimeDescriptor();
const canvas = requiredElement<HTMLCanvasElement>("game");
const score = requiredElement<HTMLOutputElement>("score");
const length = requiredElement<HTMLOutputElement>("length");
const provenance = requiredElement<HTMLOutputElement>("runtime-provenance");
const assets = requiredElement<HTMLOutputElement>("asset-status");
const status = requiredElement<HTMLSpanElement>("runtime-status");
const error = requiredElement<HTMLParagraphElement>("startup-error");
const buttons = Array.from(document.querySelectorAll<HTMLButtonElement>("[data-direction]"));
status.textContent = "Chargement assets…";
const assetMetadata = await loadSnakeTauriAssets();
assets.value = `${assetMetadata.gameKind} / engine-v${assetMetadata.engineGeneration}`;
frontendInfo(`Snake Tauri assets ready: ${assetMetadata.game} / ${assets.value}`);
status.textContent = "Chargement WASM…";
const session = await startGame(canvas, score, length, provenance, descriptor);
bindInputs(session, buttons);
window.addEventListener("resize", () => {
session.refreshDeviceClass();
session.renderNow();
});
window.addEventListener("pagehide", () => session.dispose(), { once: true });
document.body.dataset.runtimeState = "ready";
status.textContent = "Prêt";
error.hidden = true;
canvas.focus();
await reportFrontendReady();
frontendInfo(`Snake Tauri frontend ready: ${provenance.value}`);
}
void bootstrap().catch(reason => {
const message = reason instanceof Error ? reason.stack ?? reason.message : String(reason);
document.body.dataset.runtimeState = "error";
const status = document.getElementById("runtime-status");
const error = document.getElementById("startup-error");
if (status !== null) {
status.textContent = "Erreur";
}
if (error !== null) {
error.textContent = `Impossible de démarrer Snake : ${message}`;
error.hidden = false;
}
frontendError(`Snake Tauri frontend bootstrap failed: ${message}`);
});