From eea45b5f579919978aa516e88be7a14031660178 Mon Sep 17 00:00:00 2001 From: rexim Date: Tue, 2 Jul 2024 03:16:24 +0700 Subject: [PATCH] Factor player controls into hot-reloadable game module --- game.js | 27 +++++++++++++++++++++++++++ game.ts | 33 ++++++++++++++++++++++++++++++++- index.js | 43 ++++++++----------------------------------- index.ts | 44 ++++++++------------------------------------ 4 files changed, 75 insertions(+), 72 deletions(-) diff --git a/game.js b/game.js index 4e15892..bdb76e5 100644 --- a/game.js +++ b/game.js @@ -261,6 +261,10 @@ export function createPlayer(position, direction) { return { position: position, direction: direction, + movingForward: false, + movingBackward: false, + turningLeft: false, + turningRight: false, }; } function playerFovRange(player) { @@ -403,6 +407,29 @@ function renderFloorIntoImageData(imageData, player, scene) { } } export function renderGameIntoImageData(ctx, backCtx, backImageData, deltaTime, player, scene) { + let velocity = Vector2.zero(); + let angularVelocity = 0.0; + if (player.movingForward) { + velocity = velocity.add(Vector2.angle(player.direction).scale(PLAYER_SPEED)); + } + if (player.movingBackward) { + velocity = velocity.sub(Vector2.angle(player.direction).scale(PLAYER_SPEED)); + } + if (player.turningLeft) { + angularVelocity -= Math.PI; + } + if (player.turningRight) { + angularVelocity += Math.PI; + } + player.direction = player.direction + angularVelocity * deltaTime; + const nx = player.position.x + velocity.x * deltaTime; + if (sceneCanRectangleFitHere(scene, new Vector2(nx, player.position.y), Vector2.scalar(PLAYER_SIZE))) { + player.position.x = nx; + } + const ny = player.position.y + velocity.y * deltaTime; + if (sceneCanRectangleFitHere(scene, new Vector2(player.position.x, ny), Vector2.scalar(PLAYER_SIZE))) { + player.position.y = ny; + } const minimapPosition = Vector2.zero().add(canvasSize(ctx).scale(0.03)); const cellSize = ctx.canvas.width * 0.03; const minimapSize = sceneSize(scene).scale(cellSize); diff --git a/game.ts b/game.ts index 74d2c49..5ddfb72 100644 --- a/game.ts +++ b/game.ts @@ -283,12 +283,20 @@ function castRay(scene: Scene, p1: Vector2, p2: Vector2): Vector2 { export interface Player { position: Vector2; direction: number; + movingForward: boolean; + movingBackward: boolean; + turningLeft: boolean; + turningRight: boolean; } export function createPlayer(position: Vector2, direction: number): Player { return { position: position, direction: direction, + movingForward: false, + movingBackward: false, + turningLeft: false, + turningRight: false, } } @@ -450,6 +458,30 @@ function renderFloorIntoImageData(imageData: ImageData, player: Player, scene: S } export function renderGameIntoImageData(ctx: CanvasRenderingContext2D, backCtx: OffscreenCanvasRenderingContext2D, backImageData: ImageData, deltaTime: number, player: Player, scene: Scene) { + let velocity = Vector2.zero(); + let angularVelocity = 0.0; + if (player.movingForward) { + velocity = velocity.add(Vector2.angle(player.direction).scale(PLAYER_SPEED)) + } + if (player.movingBackward) { + velocity = velocity.sub(Vector2.angle(player.direction).scale(PLAYER_SPEED)) + } + if (player.turningLeft) { + angularVelocity -= Math.PI; + } + if (player.turningRight) { + angularVelocity += Math.PI; + } + player.direction = player.direction + angularVelocity*deltaTime; + const nx = player.position.x + velocity.x*deltaTime; + if (sceneCanRectangleFitHere(scene, new Vector2(nx, player.position.y), Vector2.scalar(PLAYER_SIZE))) { + player.position.x = nx; + } + const ny = player.position.y + velocity.y*deltaTime; + if (sceneCanRectangleFitHere(scene, new Vector2(player.position.x, ny), Vector2.scalar(PLAYER_SIZE))) { + player.position.y = ny; + } + const minimapPosition = Vector2.zero().add(canvasSize(ctx).scale(0.03)); const cellSize = ctx.canvas.width*0.03; const minimapSize = sceneSize(scene).scale(cellSize); @@ -467,4 +499,3 @@ export function renderGameIntoImageData(ctx: CanvasRenderingContext2D, backCtx: ctx.fillStyle = "white" ctx.fillText(`${Math.floor(1/deltaTime)}`, 100, 100); } - diff --git a/index.js b/index.js index 20eb77d..63b74c8 100644 --- a/index.js +++ b/index.js @@ -67,24 +67,20 @@ async function loadImageData(url) { if (backCtx === null) throw new Error("2D context is not supported"); backCtx.imageSmoothingEnabled = false; - let movingForward = false; - let movingBackward = false; - let turningLeft = false; - let turningRight = false; window.addEventListener("keydown", (e) => { if (!e.repeat) { switch (e.code) { case 'KeyW': - movingForward = true; + player.movingForward = true; break; case 'KeyS': - movingBackward = true; + player.movingBackward = true; break; case 'KeyA': - turningLeft = true; + player.turningLeft = true; break; case 'KeyD': - turningRight = true; + player.turningRight = true; break; } } @@ -93,16 +89,16 @@ async function loadImageData(url) { if (!e.repeat) { switch (e.code) { case 'KeyW': - movingForward = false; + player.movingForward = false; break; case 'KeyS': - movingBackward = false; + player.movingBackward = false; break; case 'KeyA': - turningLeft = false; + player.turningLeft = false; break; case 'KeyD': - turningRight = false; + player.turningRight = false; break; } } @@ -111,29 +107,6 @@ async function loadImageData(url) { const frame = (timestamp) => { const deltaTime = (timestamp - prevTimestamp) / 1000; prevTimestamp = timestamp; - let velocity = game.Vector2.zero(); - let angularVelocity = 0.0; - if (movingForward) { - velocity = velocity.add(game.Vector2.angle(player.direction).scale(game.PLAYER_SPEED)); - } - if (movingBackward) { - velocity = velocity.sub(game.Vector2.angle(player.direction).scale(game.PLAYER_SPEED)); - } - if (turningLeft) { - angularVelocity -= Math.PI; - } - if (turningRight) { - angularVelocity += Math.PI; - } - player.direction = player.direction + angularVelocity * deltaTime; - const nx = player.position.x + velocity.x * deltaTime; - if (game.sceneCanRectangleFitHere(scene, new game.Vector2(nx, player.position.y), game.Vector2.scalar(game.PLAYER_SIZE))) { - player.position.x = nx; - } - const ny = player.position.y + velocity.y * deltaTime; - if (game.sceneCanRectangleFitHere(scene, new game.Vector2(player.position.x, ny), game.Vector2.scalar(game.PLAYER_SIZE))) { - player.position.y = ny; - } game.renderGameIntoImageData(ctx, backCtx, backImageData, deltaTime, player, scene); window.requestAnimationFrame(frame); }; diff --git a/index.ts b/index.ts index 124220d..361c8cb 100644 --- a/index.ts +++ b/index.ts @@ -73,28 +73,23 @@ async function loadImageData(url: string): Promise { if (backCtx === null) throw new Error("2D context is not supported"); backCtx.imageSmoothingEnabled = false; - let movingForward = false; - let movingBackward = false; - let turningLeft = false; - let turningRight = false; - window.addEventListener("keydown", (e) => { if (!e.repeat) { switch (e.code) { - case 'KeyW': movingForward = true; break; - case 'KeyS': movingBackward = true; break; - case 'KeyA': turningLeft = true; break; - case 'KeyD': turningRight = true; break; + case 'KeyW': player.movingForward = true; break; + case 'KeyS': player.movingBackward = true; break; + case 'KeyA': player.turningLeft = true; break; + case 'KeyD': player.turningRight = true; break; } } }); window.addEventListener("keyup", (e) => { if (!e.repeat) { switch (e.code) { - case 'KeyW': movingForward = false; break; - case 'KeyS': movingBackward = false; break; - case 'KeyA': turningLeft = false; break; - case 'KeyD': turningRight = false; break; + case 'KeyW': player.movingForward = false; break; + case 'KeyS': player.movingBackward = false; break; + case 'KeyA': player.turningLeft = false; break; + case 'KeyD': player.turningRight = false; break; } } }); @@ -103,29 +98,6 @@ async function loadImageData(url: string): Promise { const frame = (timestamp: number) => { const deltaTime = (timestamp - prevTimestamp)/1000; prevTimestamp = timestamp; - let velocity = game.Vector2.zero(); - let angularVelocity = 0.0; - if (movingForward) { - velocity = velocity.add(game.Vector2.angle(player.direction).scale(game.PLAYER_SPEED)) - } - if (movingBackward) { - velocity = velocity.sub(game.Vector2.angle(player.direction).scale(game.PLAYER_SPEED)) - } - if (turningLeft) { - angularVelocity -= Math.PI; - } - if (turningRight) { - angularVelocity += Math.PI; - } - player.direction = player.direction + angularVelocity*deltaTime; - const nx = player.position.x + velocity.x*deltaTime; - if (game.sceneCanRectangleFitHere(scene, new game.Vector2(nx, player.position.y), game.Vector2.scalar(game.PLAYER_SIZE))) { - player.position.x = nx; - } - const ny = player.position.y + velocity.y*deltaTime; - if (game.sceneCanRectangleFitHere(scene, new game.Vector2(player.position.x, ny), game.Vector2.scalar(game.PLAYER_SIZE))) { - player.position.y = ny; - } game.renderGameIntoImageData(ctx, backCtx, backImageData, deltaTime, player, scene); window.requestAnimationFrame(frame); }