diff --git a/app/src/js/game.ts b/app/src/js/game.ts
index f6938ff..11987ce 100644
--- a/app/src/js/game.ts
+++ b/app/src/js/game.ts
@@ -1,4 +1,4 @@
-import { type Message, Context } from "../shared/types.js"
+import { type Message, GameContext } from "../shared/types.js"
import { focusInput } from "./focus.js"
import { $ } from "./dom.js"
import { randomId } from "../shared/utils.js"
@@ -6,40 +6,54 @@ import { setStatus, addOutput } from "./scrollback.js"
import { browserCommands } from "./commands.js"
let oldMode = "cinema"
+let stopGame = false
+let canvas: HTMLCanvasElement
+type Game = { init?: () => void, update?: (delta: number) => void, draw?: (ctx: GameContext) => void }
export async function handleGameStart(msg: Message) {
const msgId = msg.id as string
const name = msg.data as string
- const game = await import(`/command/${name}`)
- const id = randomId()
- let stopGame = false
- addOutput(msgId, { html: `` })
+ let game
+ try {
+ game = await import(`/command/${name}`)
+ } catch (err: any) {
+ setStatus(msgId, "error")
+ addOutput(msgId, `Error: ${err.message ? err.message : err}`)
+ return
+ }
+
+ const canvasId = randomId()
+ addOutput(msgId, { html: `` })
if (document.body.dataset.mode === "tall") {
browserCommands.mode?.()
oldMode = "tall"
}
- setStatus(msgId, "ok")
-
- const canvas = $(id) as HTMLCanvasElement
- const ctx = new Context(canvas.getContext("2d")!)
+ canvas = $(canvasId) as HTMLCanvasElement
canvas.focus()
- canvas.addEventListener("keydown", e => {
- e.preventDefault()
+ setStatus(msgId, "ok")
+ canvas.addEventListener("keydown", handleKeydown)
+ gameLoop(new GameContext(canvas.getContext("2d")!), game)
+}
- if (e.key === "Escape" || (e.ctrlKey && e.key === "c")) {
- stopGame = true
- if (oldMode === "tall") browserCommands.mode?.()
- canvas.classList.remove("active")
- canvas.style.height = canvas.height / 2 + "px"
- canvas.style.width = canvas.width / 2 + "px"
- focusInput()
- }
- })
+function handleKeydown(e: KeyboardEvent) {
+ e.preventDefault()
+ if (e.key === "Escape" || (e.ctrlKey && e.key === "c")) {
+ stopGame = true
+ if (oldMode === "tall") browserCommands.mode?.()
+ canvas.classList.remove("active")
+ canvas.style.height = canvas.height / 2 + "px"
+ canvas.style.width = canvas.width / 2 + "px"
+ focusInput()
+ }
+}
+
+function gameLoop(ctx: GameContext, game: Game) {
let last = 0
+
function loop(ts: number) {
if (stopGame) return
@@ -51,6 +65,6 @@ export async function handleGameStart(msg: Message) {
}
requestAnimationFrame(loop)
}
- requestAnimationFrame(loop)
-}
+ requestAnimationFrame(loop)
+}
\ No newline at end of file
diff --git a/app/src/shared/types.ts b/app/src/shared/types.ts
index a22c041..fd868b5 100644
--- a/app/src/shared/types.ts
+++ b/app/src/shared/types.ts
@@ -16,7 +16,7 @@ export type CommandResult = {
output: CommandOutput
}
-export class Context {
+export class GameContext {
height = 540
width = 960