import { Game } from "."; import { Miscellaneous, loadAssets } from "./config"; import { Player, FunctionBox, Wall } from "./entities"; import { Grid, FacingDirection, Input, Render } from "./systems"; export class TheAbstractionEngine { private game: Game; private ctx: CanvasRenderingContext2D; private animationFrameId: number | null; constructor(game: Game, ctx: CanvasRenderingContext2D) { this.game = game; this.ctx = ctx; this.animationFrameId = null; } public async init() { await loadAssets(); const inputSystem = new Input(); this.addWindowEventListenersToInputSystem(inputSystem); const facingDirectionSystem = new FacingDirection(inputSystem); [ inputSystem, facingDirectionSystem, new Grid( { width: Miscellaneous.GRID_COLUMNS, height: Miscellaneous.GRID_ROWS }, { width: Miscellaneous.GRID_CELL_WIDTH, height: Miscellaneous.GRID_CELL_HEIGHT, }, ), new Render(this.ctx), ].forEach((system) => this.game.addSystem(system)); const player = new Player(); this.game.addEntity(player); const box = new FunctionBox({ x: 3, y: 1 }, "λ x . (x)"); this.game.addEntity(box); const box2 = new FunctionBox({ x: 4, y: 1 }, "λ x . (x)"); this.game.addEntity(box2); const wall = new Wall({ x: 5, y: 3 }); this.game.addEntity(wall); } public play() { this.game.start(); const loop = (timestamp: number) => { this.game.doGameLoop(timestamp); this.animationFrameId = requestAnimationFrame(loop); // tail call recursion! /s }; this.animationFrameId = requestAnimationFrame(loop); } public stop() { if (this.animationFrameId) { cancelAnimationFrame(this.animationFrameId); this.animationFrameId = null; } } private addWindowEventListenersToInputSystem(input: Input) { window.addEventListener("keydown", (e) => { if (!e.repeat) { input.keyPressed(e.key.toLowerCase()); } }); window.addEventListener("keyup", (e) => input.keyReleased(e.key.toLowerCase()), ); window.addEventListener("blur", () => input.clearKeys()); window.addEventListener("mousemove", (e) => { const canvas = this.ctx.canvas; const rect = canvas.getBoundingClientRect(); const scaleX = canvas.width / rect.width; const scaleY = canvas.height / rect.height; const x = (e.clientX - rect.left) * scaleX; const y = (e.clientY - rect.top) * scaleY; input.setMousePosition({ x, y }); }); } }