/** * Molehill — a whack-a-mole you play with the MOUSE and nothing else. * * No character body, no keyboard, no gravity. Nine holes, a mole that pops out * of one of them, three misses before they win. The engine's `Clickable` turns * each mole into a node that reports being clicked; the built-in `ScoreKeeper` * holds the score and the misses; the wiring between them is `game.scene.json`. * * It is the starter for a whole family the other templates do not cover — * match-3, tower defense, cards, point-and-click, RTS, board games, idle. */ import { createGame2D, showBootFailure } from 'incanto/2d'; import { useEffect, useRef } from 'react'; import { Molehill, Scoreboard } from './behaviors'; import sceneJson from './game.scene.json'; export function App() { const canvasRef = useRef(null); useEffect(() => { const canvas = canvasRef.current; // StrictMode runs this effect twice against the SAME canvas element, and a // second engine on one canvas is two renderers fighting for one context. // The flag lives on the element, so it lasts exactly as long as the thing // it guards — a page-level game like this one never unmounts otherwise. if (!canvas || (canvas as { _incanto?: true })._incanto) return; (canvas as { _incanto?: true })._incanto = true; void (async () => { /** Dev-only surfaces: the ☰ debug overlay, and the editor behind it. */ const DEBUG = import.meta.env.VITE_INCANTO_DEBUG === '1'; try { const game = await createGame2D({ canvas, scene: sceneJson, behaviors: { Molehill, Scoreboard }, // The cursor is the input. `lockOnClick` would HIDE it, which is exactly // wrong for a game you play by pointing — the pointer is attached for its // position, and nothing else. pointer: { lockOnClick: false }, debug: DEBUG, // Gated on the same flag: `editor` DEFAULTS to `debug`, so a bare object // here turns it on in a production build — and this file also hangs the // game handle off `globalThis`, so `game.openEditor()` would be one line // away in a shipped build. Every other starter gates it; this one did not. editor: DEBUG && { library: true }, }); document.getElementById('loading')?.remove(); (globalThis as { game?: unknown }).game = game; } catch (error) { showBootFailure(error); } })(); }, []); return ; }