68 lines
2.8 KiB
TypeScript
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}`);
|
|
});
|