From ab8a6b02ce0a1736dd4432dc64882960b91addec Mon Sep 17 00:00:00 2001 From: Chris Wanstrath Date: Sat, 27 Sep 2025 19:18:40 -0700 Subject: [PATCH] game tweaks --- app/src/js/game.ts | 58 +++++++++++++++++++++++++---------------- app/src/shared/types.ts | 2 +- 2 files changed, 37 insertions(+), 23 deletions(-) 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