diff --git a/src/lib/ecs/System.ts b/src/lib/ecs/System.ts index 847b7fe..39bc235 100644 --- a/src/lib/ecs/System.ts +++ b/src/lib/ecs/System.ts @@ -10,6 +10,7 @@ export default abstract class BaseSystem { this.querySystem = querySystem; } + abstract start(): void; abstract update(dt: number, entities: Entity[]): void; abstract destroy(): void; } diff --git a/src/lib/ecs/systems/CameraSystem.ts b/src/lib/ecs/systems/CameraSystem.ts index 219bd2e..246a42e 100644 --- a/src/lib/ecs/systems/CameraSystem.ts +++ b/src/lib/ecs/systems/CameraSystem.ts @@ -15,7 +15,7 @@ export default class CameraSystem extends System { requiredComponents = [CameraComponent, PositionComponent]; protected positionMap: PositionMap; - + protected readonly width: number = 640; protected readonly height: number = 480; protected readonly rayMaxDistanceRay = 10; @@ -23,14 +23,16 @@ export default class CameraSystem extends System { protected readonly level: Level; protected readonly canvas: Canvas; + protected readonly container: HTMLElement; constructor(querySystem: QuerySystem, container: HTMLElement, level: Level) { super(querySystem); - + const cols = level.map[0].length; const rows = level.map.length; this.level = level; + this.container = container; this.canvas = new Canvas({ height: this.height, @@ -39,21 +41,25 @@ export default class CameraSystem extends System { this.positionMap = new PositionMap(cols, rows); - this.querySystem.query([PositionComponent, CollisionComponent, TextureComponent]).forEach(entity => { - if (entity.hasComponent(CameraComponent)) { - return; - } + this.querySystem + .query([PositionComponent, CollisionComponent, TextureComponent]) + .forEach((entity) => { + if (entity.hasComponent(CameraComponent)) { + return; + } - const position = entity.getComponent(PositionComponent); + const position = entity.getComponent(PositionComponent); - this.positionMap.set( - Math.floor(position.x), - Math.floor(position.y), - entity - ); - }) + this.positionMap.set( + Math.floor(position.x), + Math.floor(position.y), + entity + ); + }); + } - container.appendChild(this.canvas.element); + start() { + this.container.appendChild(this.canvas.element); } update(_: number, entities: Entity[]) { @@ -89,9 +95,10 @@ export default class CameraSystem extends System { let rayAngle = cameraAngle.angle - cameraFov.fov / 2; for (let rayCount = 0; rayCount < width; rayCount++) { - - const cosineIncrement = Math.cos(degreeToRadians(rayAngle)) / this.rayPrecision; - const sinusIncrement = Math.sin(degreeToRadians(rayAngle)) / this.rayPrecision; + const cosineIncrement = + Math.cos(degreeToRadians(rayAngle)) / this.rayPrecision; + const sinusIncrement = + Math.sin(degreeToRadians(rayAngle)) / this.rayPrecision; let currentRayX = initialRayX; let currentRayY = initialRayY; @@ -104,7 +111,7 @@ export default class CameraSystem extends System { currentRayY += sinusIncrement; rayCollidedEntity = this.positionMap.get( - Math.floor(currentRayX), + Math.floor(currentRayX), Math.floor(currentRayY) ); @@ -113,8 +120,8 @@ export default class CameraSystem extends System { } distanceRay = Math.sqrt( - Math.pow(cameraPosition.x - currentRayX, 2) - + Math.pow(cameraPosition.y - currentRayY, 2) + Math.pow(cameraPosition.x - currentRayX, 2) + + Math.pow(cameraPosition.y - currentRayY, 2) ); if (distanceRay >= this.rayMaxDistanceRay) { @@ -156,7 +163,7 @@ export default class CameraSystem extends System { wallHeight ); } -/* + /* this._drawFloor({ x: rayCount, position: cameraPosition, @@ -176,7 +183,7 @@ export default class CameraSystem extends System { rayX: number, rayY: number, texture: Texture, - wallHeight: number, + wallHeight: number ) { const texturePositionX = Math.floor( (texture.width * (rayX + rayY)) % texture.width @@ -185,7 +192,7 @@ export default class CameraSystem extends System { let y = this.height / 2 - wallHeight; for (let i = 0; i < texture.height; i++) { - const y1 = y + const y1 = y; const y2 = y + (yIncrementer + 0.5) + 1; y += yIncrementer; @@ -209,15 +216,15 @@ export default class CameraSystem extends System { position, wallHeight, angle, - rayAngle -}: { - x: number, - texture: Texture, - position: PositionComponent, - wallHeight: number, - angle: number, - rayAngle: number -}) { + rayAngle, + }: { + x: number; + texture: Texture; + position: PositionComponent; + wallHeight: number; + angle: number; + rayAngle: number; + }) { const halfHeight = this.height / 2; const start = halfHeight + wallHeight + 1; @@ -225,24 +232,27 @@ export default class CameraSystem extends System { const directionSin = Math.sin(degreeToRadians(rayAngle)); for (let y = start; y < this.height; y++) { - // Create distance and calculate it - let distance = this.height / (2 * y - this.height); - - distance = distance / Math.cos(degreeToRadians(angle) - degreeToRadians(rayAngle)); // Inverse fisheye fix - - // Get the tile position - let tileX = distance * directionCos; - let tileY = distance * directionSin; - tileX += position.x; - tileY += position.y; - - // Define texture coords - const textureX = Math.abs(Math.floor(tileX * texture.width)) % texture.width; - const textureY = Math.abs(Math.floor(tileY * texture.height)) % texture.height; - - // Get pixel color - const color = texture.colors[textureX][textureY]; - this.canvas.drawPixel({ x, y, color }); + let distance = this.height / (2 * y - this.height); + + // Inverse fisheye fix + distance = + distance / Math.cos(degreeToRadians(angle) - degreeToRadians(rayAngle)); + + // Get the tile position + let tileX = distance * directionCos; + let tileY = distance * directionSin; + tileX += position.x; + tileY += position.y; + + // Define texture coords + const textureX = + Math.abs(Math.floor(tileX * texture.width)) % texture.width; + const textureY = + Math.abs(Math.floor(tileY * texture.height)) % texture.height; + + // Get pixel color + const color = texture.colors[textureX][textureY]; + this.canvas.drawPixel({ x, y, color }); } -} + } } diff --git a/src/lib/ecs/systems/ControlSystem.ts b/src/lib/ecs/systems/ControlSystem.ts index 7a17621..6e1ec90 100644 --- a/src/lib/ecs/systems/ControlSystem.ts +++ b/src/lib/ecs/systems/ControlSystem.ts @@ -2,7 +2,6 @@ import Entity from "src/lib/ecs/Entity"; import System from "src/lib/ecs/System"; import MoveComponent from "src/lib/ecs/components/MoveComponent"; import RotateComponent from "src/lib/ecs/components/RotateComponent"; -import QuerySystem from "../lib/QuerySystem"; const keyCodes = { up: "KeyW", @@ -20,10 +19,8 @@ export default class ControlSystem extends System { left: false, right: false, }; - - constructor(querySystem: QuerySystem) { - super(querySystem); - + + start(): void { this.createListeners(); } diff --git a/src/lib/ecs/systems/MinimapSystem.ts b/src/lib/ecs/systems/MinimapSystem.ts index 2e37819..e668487 100644 --- a/src/lib/ecs/systems/MinimapSystem.ts +++ b/src/lib/ecs/systems/MinimapSystem.ts @@ -12,28 +12,34 @@ export default class MinimapSystem extends System { readonly scale: number = 20; readonly canvas: Canvas; + protected readonly container: HTMLElement; + constructor(querySystem: QuerySystem, container: HTMLElement, level: Level) { super(querySystem); const cols = level.map[0].length; const rows = level.map.length; + this.container = container; + this.canvas = new Canvas({ height: rows * this.scale, width: cols * this.scale, }); + } - container.appendChild(this.canvas.element); + start() { + this.container.appendChild(this.canvas.element); } update(_: number, entities: Entity[]) { this.canvas.clear(); - entities.forEach(entity => { + entities.forEach((entity) => { const { x, y } = entity.getComponent(PositionComponent); const { color } = entity.getComponent(ColorComponent); const { size } = entity.getComponent(BoxComponent); - + this.drawSquare(x, y, size, color); }); } diff --git a/src/lib/ecs/systems/MoveSystem.ts b/src/lib/ecs/systems/MoveSystem.ts index 4c2e84b..4e79cae 100644 --- a/src/lib/ecs/systems/MoveSystem.ts +++ b/src/lib/ecs/systems/MoveSystem.ts @@ -15,7 +15,6 @@ export default class MoveSystem extends System { protected positionMap: PositionMap; - constructor(querySystem: QuerySystem, level: Level) { super(querySystem); @@ -39,6 +38,7 @@ export default class MoveSystem extends System { }) } + start(): void {} destroy(): void {} update(dt: number, entities: Entity[]) { diff --git a/src/main.ts b/src/main.ts index 58bfb85..6a3d9e9 100644 --- a/src/main.ts +++ b/src/main.ts @@ -22,7 +22,6 @@ window.onload = async () => { 'press any key' ]); - const gameScene = new LevelScene({ container, level, @@ -34,18 +33,19 @@ window.onload = async () => { 'You win' ]); - introScene.render(); + introScene.start(); + introScene.onComplete(() => { introScene.destroy() soundManager.play('background'); - gameScene.run(); + gameScene.start(); }); gameScene.onComplete(() => { soundManager.pause('background'); gameScene.destroy(); - winScene.render(); + winScene.start(); }) } catch (err) { diff --git a/src/scenes/BaseScene.ts b/src/scenes/BaseScene.ts index edd97d1..8b5f256 100644 --- a/src/scenes/BaseScene.ts +++ b/src/scenes/BaseScene.ts @@ -1,5 +1,5 @@ export default interface BaseScene { onComplete(cb: () => void): void; - render(container: HTMLElement): void; + start(): void; destroy(): void; } \ No newline at end of file diff --git a/src/scenes/LevelScene.ts b/src/scenes/LevelScene.ts index 3bfb192..fdd5a35 100644 --- a/src/scenes/LevelScene.ts +++ b/src/scenes/LevelScene.ts @@ -11,6 +11,7 @@ import { createEntities } from "src/lib/world"; import QuerySystem from "src/lib/ecs/lib/QuerySystem"; import CameraComponent from "src/lib/ecs/components/CameraComponent"; import PositionComponent from "src/lib/ecs/components/PositionComponent"; +import BaseScene from "./BaseScene"; interface LevelSceneProps { container: HTMLElement; @@ -19,7 +20,7 @@ interface LevelSceneProps { textureManager: TextureManager; } -export default class LevelScene { +export default class LevelScene implements BaseScene { protected readonly level: Level; protected readonly loop: Loop; protected onCompleteCallback?: () => void; @@ -68,7 +69,10 @@ export default class LevelScene { this.onCompleteCallback = cb; }; - run() { + start() { + this.systems.forEach(system => { + system.start(); + }); this.loop.play(); } @@ -78,6 +82,7 @@ export default class LevelScene { system.destroy(); }) } + /* createListeners() { document.addEventListener("pointerdown", this.handleDocumentPointerdown); diff --git a/src/scenes/TitleScene.ts b/src/scenes/TitleScene.ts index 29e547b..b9dc941 100644 --- a/src/scenes/TitleScene.ts +++ b/src/scenes/TitleScene.ts @@ -3,20 +3,21 @@ import BaseScene from "./BaseScene"; export default class TitleScene implements BaseScene { protected readonly view: TextContent; + protected readonly container: HTMLElement; protected onCompleteCallback?: () => void; constructor(container: HTMLElement, text: string[]) { + this.container = container; this.view = new TextContent(text); this.createListeners(); - - container.appendChild(this.view.canvas.element); } onComplete(cb: () => void): void { this.onCompleteCallback = cb; } - render() { + start() { + this.container.appendChild(this.view.canvas.element); this.view.render(); }