Optimise
All checks were successful
Check & deploy / build (pull_request) Successful in 1m51s

This commit is contained in:
Andras Schmelczer 2026-05-21 20:33:49 +01:00
parent 6bc125be1c
commit ed5a4379db
76 changed files with 1418 additions and 988 deletions

View file

@ -32,6 +32,15 @@ const main = async () => {
let game: GameLoop | null = null;
let configPane: ConfigPane | null = null;
const getGame = () => game;
const destroyCurrentGame = async () => {
const currentGame = game;
if (!currentGame) {
return;
}
game = null;
await currentGame.destroy();
};
const errorPresenter = new ErrorPresenter(
queryRequiredElement('.errors-container', HTMLElement)
@ -40,7 +49,7 @@ const main = async () => {
errorPresenter.render(error);
if (error.severity === Severity.ERROR) {
document.body.classList.remove('is-loading');
game?.destroy();
void destroyCurrentGame();
shouldStop = true;
}
});
@ -53,19 +62,24 @@ const main = async () => {
const grainOverlay = queryRequiredElement('.garden-grain', HTMLDivElement);
const promptElement = queryRequiredElement('.garden-prompt', HTMLDivElement);
const exportStatus = queryRequiredElement('.export-status', HTMLSpanElement);
const settingsButton = queryRequiredElement('button.settings', HTMLButtonElement);
const restartButton = queryRequiredElement('button.restart', HTMLButtonElement);
const infoButton = queryRequiredElement('button.info', HTMLButtonElement);
const settingsButton = queryRequiredElement(
'[data-control="settings"]',
HTMLButtonElement
);
const restartButton = queryRequiredElement(
'[data-control="restart"]',
HTMLButtonElement
);
const infoButton = queryRequiredElement('[data-control="info"]', HTMLButtonElement);
const infoElement = queryRequiredElement('.info-page', HTMLElement);
const minimizeFullScreenButton = queryRequiredElement(
'button.minimize-full-screen',
const fullScreenButton = queryRequiredElement(
'[data-control="full-screen"]',
HTMLButtonElement
);
const maximizeFullScreenButton = queryRequiredElement(
'button.maximize-full-screen',
const export4kButton = queryRequiredElement(
'[data-control="export"]',
HTMLButtonElement
);
const export4kButton = queryRequiredElement('.export-4k', HTMLButtonElement);
const splash = new SplashScreen();
const paletteControl = new PaletteControl({
@ -103,11 +117,7 @@ const main = async () => {
!configPane?.isOpen &&
!infoPageHandler.isOpen
);
new FullScreenHandler(
minimizeFullScreenButton,
maximizeFullScreenButton,
document.documentElement
);
new FullScreenHandler(fullScreenButton, document.documentElement);
new VibeNavigator({
onChange: ({ vibeId, vibeName, source }) => {
@ -119,16 +129,17 @@ const main = async () => {
},
});
restartButton.addEventListener('click', () => game?.destroy());
restartButton.addEventListener('click', () => void destroyCurrentGame());
export4kButton.addEventListener('click', async () => {
if (!game || export4kButton.disabled) {
const currentGame = game;
if (!currentGame || export4kButton.disabled) {
return;
}
export4kButton.disabled = true;
try {
await game.exportSnapshot();
await currentGame.exportSnapshot();
trackExport({ vibeId: activeVibe.id });
} catch (error) {
ErrorHandler.addException(error, { severity: Severity.WARNING });
@ -168,9 +179,15 @@ const main = async () => {
);
const gpu = await gpuPromise;
const gpuNavigator = navigator.gpu;
if (!gpuNavigator) {
throw new Error('WebGPU is no longer available after initialization.');
}
const canvasFormat = gpuNavigator.getPreferredCanvasFormat();
configPane = new ConfigPane({
maxSupportedAgentCount: getMaxSupportedAgentCount(gpu),
settingsButton,
onOpen: () => infoPageHandler.close(),
onConfigChange: () => {
game?.onVibeChanged();
syncRuntimeUi();
@ -186,13 +203,14 @@ const main = async () => {
let isFirstStart = true;
while (!shouldStop) {
game = new GameLoop(canvas, gpu, deltaTimeCalculator, {
const loop = new GameLoop(canvas, gpu, canvasFormat, deltaTimeCalculator, {
toolbar: toolbarRow,
prompt: promptElement,
eraserPreview,
grainOverlay,
exportStatus,
});
game = loop;
syncRuntimeUi();
audioControl.render();
@ -211,8 +229,11 @@ const main = async () => {
requestAnimationFrame(() => document.body.classList.remove('is-loading'))
);
}
game.attachPointerInput();
await game.start();
loop.attachPointerInput();
await loop.start();
if (game === loop) {
game = null;
}
}
} catch (e) {
document.body.classList.remove('is-loading');