export class Gamelib { constructor(console, assetProvider, canvasElement) { this.console = console; this.assetProvider = assetProvider; this.canvas = canvasElement; this.width = 480; this.height = 360; this.canvas.width = this.width; this.canvas.height = this.height; this.cx = this.canvas.getContext("2d"); this.cx.imageSmootingEnabled = false; this.loopInterval = null; this.keysPressed = new Set(); this.keyPressHandlers = new Map(); this.keyReleaseHandlers = new Map(); this.mouseMoveHandler = null; this.mouseButtonsPressed = new Set(); this.mouseDownHandlers = new Map(); this.mouseUpHandlers = new Map(); this.mouseX = null; this.mouseY = null; } init() { document.body.addEventListener("keydown", this.keydownListener.bind(this)); document.body.addEventListener("keyup", this.keyupListener.bind(this)); this.canvas.addEventListener("mousemove", this.mousemoveListener.bind(this)); this.canvas.addEventListener("mousedown", this.mousedownListener.bind(this)); this.canvas.addEventListener("mouseup", this.mouseupListener.bind(this)); this.canvas.addEventListener("contextmenu", this.contextMenuListener.bind(this)); } destroy() { document.body.removeEventListener("keydown", this.keydownListener); document.body.removeEventListener("keyup", this.keyupListener); this.canvas.removeEventListener("mousemove", this.mousemoveListener); this.canvas.removeEventListener("mousedown", this.mousedownListener); this.canvas.removeEventListener("mouseup", this.mouseupListener); this.canvas.removeEventListener("contextmenu", this.contextMenuListener); clearInterval(this.loopInterval); } startGameLoop(loopFunction) { let before = Date.now(); this.loopInterval = setInterval(() => { const now = Date.now(); const deltaT = (now - before) / 1000; before = now; try { loopFunction(deltaT); } catch (error) { this.console.error(error); } }, 16); } keydownListener(ev) { this.keysPressed.add(ev.key); this.keyPressHandlers.get(ev.key)?.(); } keyupListener(ev) { this.keysPressed.delete(ev.key); this.keyReleaseHandlers.get(ev.key)?.(); } mousemoveListener(ev) { const ratioX = this.canvas.width / this.canvas.clientWidth; const ratioY = this.canvas.height / this.canvas.clientHeight; this.mouseX = ev.offsetX * ratioX; this.mouseY = ev.offsetY * ratioY; this.mouseMoveHandler?.( ev.offsetX * ratioX, ev.offsetY * ratioY, ev.movementX * ratioX, ev.movementY * ratioY, ); } mousedownListener(ev) { const ratioX = this.canvas.width / this.canvas.clientWidth; const ratioY = this.canvas.height / this.canvas.clientHeight; this.mouseButtonsPressed.add(ev.button); this.mouseDownHandlers.get(ev.button)?.(ev.offsetX * ratioX, ev.offsetY * ratioY); } mouseupListener(ev) { const ratioX = this.canvas.width / this.canvas.clientWidth; const ratioY = this.canvas.height / this.canvas.clientHeight; this.mouseButtonsPressed.delete(ev.button); this.mouseUpHandlers.get(ev.button)?.(ev.offsetX * ratioX, ev.offsetY * ratioY); } contextMenuListener(ev) { ev.preventDefault(); } drawSprite(x, y, width, height, name) { const cx = this.cx; const image = new Image(); image.src = this.assetProvider.url(name); image.onload = () => { cx.drawImage(image, x, y, width, height); }; } clear(color) { const cx = this.cx; cx.fillStyle = color; cx.fillRect(0, 0, this.width, this.height); } drawRect(x, y, width, height, color) { const cx = this.cx; cx.fillStyle = color; cx.fillRect(x, y, width, height); } getAdapter() { return new GamelibAdapter(this); } } export class GamelibAdapter { MouseButton = { Left: 0, Right: 1, Middle: 2, }; constructor(gamelib) { this.gamelib = gamelib; } get width() { return this.gamelib.width; } get height() { return this.gamelib.height; } get mouseX() { return this.gamelib.mouseX; } get mouseY() { return this.gamelib.mouseY; } println(msg) { this.gamelib.console.log(msg); } startGameLoop(loopFunction) { this.gamelib.startGameLoop(loopFunction); } isPressed(key) { return this.gamelib.keysPressed.has(key); } onPress(key, handlerFunction) { this.gamelib.keyPressHandlers.set(key, handlerFunction); } onRelease(key, handlerFunction) { this.gamelib.keyReleaseHandlers.set(key, handlerFunction); } onMouseMove(handlerFunction) { this.gamelib.mouseMoveHandler = handlerFunction; } isClicking(button = this.MouseButton.Left) { return this.gamelib.mouseButtonsPressed.has(button); } onClick(handlerFunction, button = this.MouseButton.Left) { this.gamelib.mouseDownHandlers.set(button, handlerFunction); } onClickRelease(handlerFunction, button = this.MouseButton.Left) { this.gamelib.mouseUpHandlers.set(button, handlerFunction); } drawSprite(x, y, width, height, name) { this.gamelib.drawSprite(x, y, width, height, name); } rgb(red, green, blue) { return `rgb(${red}, ${green}, ${blue})`; } clear(color) { this.gamelib.clear(color); } drawRect(x, y, width, height, color) { this.gamelib.drawRect(x, y, width, height, color); } }