diff --git a/src/app/components/game/game.component.html b/src/app/components/game/game.component.html index 90af569..c504b00 100644 --- a/src/app/components/game/game.component.html +++ b/src/app/components/game/game.component.html @@ -7,9 +7,9 @@
- - - + + +
Step: {{ simMain.currentStep }}
diff --git a/src/app/components/game/game.component.ts b/src/app/components/game/game.component.ts index 8e39565..39da3c1 100644 --- a/src/app/components/game/game.component.ts +++ b/src/app/components/game/game.component.ts @@ -44,19 +44,25 @@ export class GameComponent { } rewind() { - if (this.simMain.currentLevel) - this.simMain.currentLevel.currentStep = -1; - - this.simMain.currentStep = -1; + const wasActive = this.visMain.active; + if (wasActive) + this.visMain.stop(); + this.simMain.rewind(); + if (wasActive) + this.visMain.start(); } startNextWave() { this.simMain.addCommand(new SimCommandStartNextWave()); - this.simMain.currentLevel!.paused = false; } fastForward() { + const wasActive = this.visMain.active; + if (wasActive) + this.visMain.stop(); this.simMain.executeToEnd(); + if (wasActive) + this.visMain.start(); } async loadGdRoot(): Promise { diff --git a/src/app/components/game/sim/SimMain.ts b/src/app/components/game/sim/SimMain.ts index f77cd24..a30b8fd 100644 --- a/src/app/components/game/sim/SimMain.ts +++ b/src/app/components/game/sim/SimMain.ts @@ -10,6 +10,7 @@ import { SimLevel } from './SimLevel'; export class SimMain { currentStep = -1; + maxStep = -1; currentLevel: SimLevel | null = null; commandHistory: SimCommand[] = []; gdRoot: GdRoot = null!; @@ -30,9 +31,7 @@ export class SimMain { } executeToEnd() { - this.executeUntilStep( - this.commandHistory[this.commandHistory.length - 1].step - ); + this.executeUntilStep(this.maxStep); } executeUntilStep(target: number) { @@ -41,8 +40,14 @@ export class SimMain { } } + rewind() { + this.currentLevel = new SimLevel(this.gdRoot, this.currentLevel?.index ?? 0); + this.currentStep = -1; + } + step() { this.currentStep++; + this.maxStep = Math.max(this.maxStep, this.currentStep); if (this.currentLevel && !this.currentLevel.paused) { this.currentLevel.currentStep++; } diff --git a/src/app/components/game/sim/commands/SimCommandStartNextWave.ts b/src/app/components/game/sim/commands/SimCommandStartNextWave.ts index cd2c87c..685818c 100644 --- a/src/app/components/game/sim/commands/SimCommandStartNextWave.ts +++ b/src/app/components/game/sim/commands/SimCommandStartNextWave.ts @@ -17,6 +17,7 @@ export class SimCommandStartNextWave extends SimCommand { level.nextWaveStep = level.currentStep + simMain.gdRoot.simulation.waveDuration * simMain.gdRoot.simulation.stepsPerSecond - 1; level.lastEnemySpawnStep = level.currentStep; level.enemiesLeftToSpawn = data.waves[level.currentWave].amount; + level.paused = false; } public check(simMain: SimMain): boolean { diff --git a/src/app/components/game/vis/VisLevel.ts b/src/app/components/game/vis/VisLevel.ts index 2ca1313..2e5537b 100644 --- a/src/app/components/game/vis/VisLevel.ts +++ b/src/app/components/game/vis/VisLevel.ts @@ -1,312 +1,305 @@ -import { AssetPreloaderService } from "../../../assetPreloaderService"; -import { GdRoot } from "../data/GdRoot"; -import { ECellType } from "../sim/ECellType"; -import { SimCell } from "../sim/SimCell"; -import { SimEnemy } from "../sim/SimEnemy"; -import { SimLevel } from "../sim/SimLevel"; -import { SimMain } from "../sim/SimMain"; -import { SimProjectile } from "../sim/SimProjectile"; -import { Hex } from "../util/Hex"; -import { Vector2 } from "../util/Vector2"; -import { VisEnemy } from "./VisEnemy"; -import { VisMain } from "./VisMain"; -import { VisProjectile } from "./VisProjectile"; +import { AssetPreloaderService } from '../../../assetPreloaderService'; +import { GdRoot } from '../data/GdRoot'; +import { ECellType } from '../sim/ECellType'; +import { SimCell } from '../sim/SimCell'; +import { SimEnemy } from '../sim/SimEnemy'; +import { SimLevel } from '../sim/SimLevel'; +import { SimMain } from '../sim/SimMain'; +import { SimProjectile } from '../sim/SimProjectile'; +import { Hex } from '../util/Hex'; +import { Vector2 } from '../util/Vector2'; +import { VisEnemy } from './VisEnemy'; +import { VisMain } from './VisMain'; +import { VisProjectile } from './VisProjectile'; export class VisLevel { - private screenCellWidth: number = -1; - private screenCellHeight: number = -1; - private screenXOffset: number = -1; - private screenYOffset: number = -1; - private hexSize: number = -1; - private lastStep: number = -1; - private projectileMap: Map; - private enemyMap: Map; - private background: HTMLCanvasElement | null = null; - private simLevel: SimLevel | null = null; - private visMain: VisMain; - private simMain: SimMain; - private gdRoot: GdRoot; - assets: AssetPreloaderService; - private hoveredHex: Hex | null = null; + private screenCellWidth: number = -1; + private screenCellHeight: number = -1; + private screenXOffset: number = -1; + private screenYOffset: number = -1; + private hexSize: number = -1; + private lastStep: number = -1; + private projectileMap: Map; + private enemyMap: Map; + private background: HTMLCanvasElement | null = null; + private simLevel: SimLevel | null = null; + private visMain: VisMain; + private simMain: SimMain; + private gdRoot: GdRoot; + assets: AssetPreloaderService; + private hoveredHex: Hex | null = null; - constructor(visMain: VisMain, simMain: SimMain, gdRoot: GdRoot, assets: AssetPreloaderService) { - this.assets = assets; - this.visMain = visMain; - this.simMain = simMain; - this.gdRoot = gdRoot - this.enemyMap = new Map(); - this.projectileMap = new Map(); - this.reset(); - } + constructor(visMain: VisMain, simMain: SimMain, gdRoot: GdRoot, assets: AssetPreloaderService) { + this.assets = assets; + this.visMain = visMain; + this.simMain = simMain; + this.gdRoot = gdRoot; + this.enemyMap = new Map(); + this.projectileMap = new Map(); + this.reset(); + } - public reset() { - this.projectileMap.clear(); - this.enemyMap.clear(); - this.background = null; - } + public reset() { + this.projectileMap.clear(); + this.enemyMap.clear(); + this.background = null; + } - public draw() { - const ctx = this.visMain.context; - const simLevel = this.simMain.currentLevel; - if (simLevel == null) { - return; - } - const gdLevel = this.gdRoot.levels[simLevel.index]; + public draw() { + const ctx = this.visMain.context; + const simLevel = this.simMain.currentLevel; + if (simLevel == null) { + return; + } + const gdLevel = this.gdRoot.levels[simLevel.index]; - if (simLevel != this.simLevel) { - this.reset(); - this.simLevel = simLevel; - } + if (simLevel != this.simLevel) { + this.reset(); + this.simLevel = simLevel; + } - this.drawBackground(); - ctx.globalCompositeOperation = "source-over"; + this.drawBackground(); + ctx.globalCompositeOperation = 'source-over'; - // Highlight hovered cell first (under everything else) - if (this.hoveredHex) { - const hoveredIdx = simLevel.getCellIndex(this.hoveredHex); - const hoveredCell = simLevel.cells[hoveredIdx]; - if (hoveredCell && hoveredCell.distance <= gdLevel.radius) { - this.drawCellImage(ctx, hoveredCell, "cell-highlighted.svg"); - } - } + // Highlight hovered cell first (under everything else) + if (this.hoveredHex) { + const hoveredIdx = simLevel.getCellIndex(this.hoveredHex); + const hoveredCell = simLevel.cells[hoveredIdx]; + if (hoveredCell && hoveredCell.distance <= gdLevel.radius) { + this.drawCellImage(ctx, hoveredCell, 'cell-highlighted.svg'); + } + } - simLevel.cells.forEach((cell: SimCell) => { - if (cell.distance > gdLevel.radius) { - return; - } - this.drawCell(cell); - }); + simLevel.cells.forEach((cell: SimCell) => { + if (cell.distance > gdLevel.radius) { + return; + } + this.drawCell(cell); + }); - simLevel.enemies.forEach((enemy: SimEnemy) => { - this.drawEnemy(enemy); - }); + simLevel.enemies.forEach((enemy: SimEnemy) => { + this.drawEnemy(enemy); + }); - simLevel.projectiles.forEach((projectile: SimProjectile) => { - this.drawProjectile(projectile); - }); + simLevel.projectiles.forEach((projectile: SimProjectile) => { + this.drawProjectile(projectile); + }); - ctx.fillStyle = "white"; - ctx.fillText("Currency: " + simLevel.currency, 5, 15); - ctx.fillText("Current wave: " + simLevel.currentWave, 5, 35); - ctx.fillText("Enemies left: " + simLevel.enemiesLeftToSpawn, 5, 55); - ctx.fillText("Current step: " + simLevel.currentStep, 5, 75); - } + ctx.fillStyle = 'white'; + ctx.fillText('Currency: ' + simLevel.currency, 5, 15); + ctx.fillText('Current wave: ' + simLevel.currentWave, 5, 35); + ctx.fillText('Enemies left: ' + simLevel.enemiesLeftToSpawn, 5, 55); + ctx.fillText('Current step: ' + simLevel.currentStep, 5, 75); + } - public updateSize() { - const simLevel = this.simMain.currentLevel; - if (simLevel == null) { - return; - } + public updateSize() { + const simLevel = this.simMain.currentLevel; + if (simLevel == null) { + return; + } - const gdLevel = this.gdRoot.levels[simLevel.index]; - const minSize = Math.min(this.visMain.canvas.height, this.visMain.canvas.width * Math.sqrt(3) / 2); - this.hexSize = Math.floor(minSize / (4 * (gdLevel.radius - 1) - 4)); - this.screenCellHeight = Math.ceil(2 * this.hexSize); - this.screenCellHeight = Math.ceil(this.screenCellHeight * 0.5) * 2; - this.screenCellWidth = Math.ceil(Math.sqrt(3) / 2 * this.screenCellHeight); - this.screenCellWidth = Math.ceil(this.screenCellWidth * 0.5) * 2; - this.screenXOffset = this.screenCellWidth * (gdLevel.radius + 0.5); - this.screenYOffset = this.screenCellHeight * (gdLevel.radius + 0.5); + const gdLevel = this.gdRoot.levels[simLevel.index]; + const minSize = Math.min(this.visMain.canvas.height, (this.visMain.canvas.width * Math.sqrt(3)) / 2); + this.hexSize = Math.floor(minSize / (4 * (gdLevel.radius - 1) - 4)); + this.screenCellHeight = Math.ceil(2 * this.hexSize); + this.screenCellHeight = Math.ceil(this.screenCellHeight * 0.5) * 2; + this.screenCellWidth = Math.ceil((Math.sqrt(3) / 2) * this.screenCellHeight); + this.screenCellWidth = Math.ceil(this.screenCellWidth * 0.5) * 2; + this.screenXOffset = this.screenCellWidth * (gdLevel.radius + 0.5); + this.screenYOffset = this.screenCellHeight * (gdLevel.radius + 0.5); - const width = this.screenCellWidth * (gdLevel.radius * 2 + 1); - const height = this.screenCellHeight * (gdLevel.radius * 2 + 1); - this.screenXOffset += (this.visMain.canvas.width - width) * 0.5; - this.screenYOffset += (this.visMain.canvas.height - height) * 0.5; + const width = this.screenCellWidth * (gdLevel.radius * 2 + 1); + const height = this.screenCellHeight * (gdLevel.radius * 2 + 1); + this.screenXOffset += (this.visMain.canvas.width - width) * 0.5; + this.screenYOffset += (this.visMain.canvas.height - height) * 0.5; - this.screenXOffset = Math.floor(this.screenXOffset); - this.screenYOffset = Math.floor(this.screenYOffset); - this.background = null; - this.enemyMap.clear(); - } + this.screenXOffset = Math.floor(this.screenXOffset); + this.screenYOffset = Math.floor(this.screenYOffset); + this.background = null; + this.enemyMap.clear(); + } - public updateEveryFrame(currentStep: number) { - const simLevel = this.simMain.currentLevel; - if (simLevel == null) { - return; - } + public updateEveryFrame(currentStep: number) { + if (currentStep < 0) { + this.lastStep = -1; + return; + } - const t = currentStep - Math.floor(currentStep); + const simLevel = this.simMain.currentLevel; + if (simLevel == null) { + return; + } - const deadEnemies: SimEnemy[] = []; - simLevel.enemies.forEach((simEnemy: SimEnemy) => { - if (simEnemy.dead) { - deadEnemies.push(simEnemy); - return; - } + const t = currentStep - Math.floor(currentStep); - const visEnemy = this.enemyMap.get(simEnemy); - if (!visEnemy) { - this.enemyMap.set(simEnemy, new VisEnemy(this.gdRoot, this.assets, simEnemy, this.screenCellWidth, this.screenCellHeight)); - } - else if (Math.floor(currentStep) != Math.floor(this.lastStep)) { - visEnemy.advanceStep(); - } - else { - visEnemy.update(t); - } - }); - for (const deadEnemy of deadEnemies) { - this.enemyMap.delete(deadEnemy); - } + const deadEnemies: SimEnemy[] = []; + simLevel.enemies.forEach((simEnemy: SimEnemy) => { + if (simEnemy.dead) { + deadEnemies.push(simEnemy); + return; + } - const deadProjectiles: SimProjectile[] = []; - simLevel.projectiles.forEach((simProjectile: SimProjectile) => { - if (simProjectile.dead) { - deadProjectiles.push(simProjectile); - return; - } + const visEnemy = this.enemyMap.get(simEnemy); + if (!visEnemy) { + this.enemyMap.set(simEnemy, new VisEnemy(this.gdRoot, this.assets, simEnemy, this.screenCellWidth, this.screenCellHeight)); + } else if (Math.floor(currentStep) != Math.floor(this.lastStep)) { + visEnemy.advanceStep(); + } else { + visEnemy.update(t); + } + }); + for (const deadEnemy of deadEnemies) { + this.enemyMap.delete(deadEnemy); + } - const visProjectile = this.projectileMap.get(simProjectile); - if (!visProjectile) { - this.projectileMap.set(simProjectile, new VisProjectile(simProjectile)); - } - else if (Math.floor(currentStep) != Math.floor(this.lastStep)) { - visProjectile.advanceStep(); - } - }); - for (const deadProjectile of deadProjectiles) { - this.projectileMap.delete(deadProjectile); - } + const deadProjectiles: SimProjectile[] = []; + simLevel.projectiles.forEach((simProjectile: SimProjectile) => { + if (simProjectile.dead) { + deadProjectiles.push(simProjectile); + return; + } - this.lastStep = currentStep; - } + const visProjectile = this.projectileMap.get(simProjectile); + if (!visProjectile) { + this.projectileMap.set(simProjectile, new VisProjectile(simProjectile)); + } else if (Math.floor(currentStep) != Math.floor(this.lastStep)) { + visProjectile.advanceStep(); + } + }); + for (const deadProjectile of deadProjectiles) { + this.projectileMap.delete(deadProjectile); + } - public setHoveredHex(hex: Hex | null) { - this.hoveredHex = hex; - } + this.lastStep = currentStep; + } - public getScreenCoords(hex: Hex): Vector2 { - const coord = Hex.toPixel(hex, this.hexSize); - return new Vector2(coord.x + this.screenXOffset - this.screenCellWidth / 2, coord.y + this.screenYOffset - this.screenCellHeight / 2); - } + public setHoveredHex(hex: Hex | null) { + this.hoveredHex = hex; + } - public getHexFromScreenCoords(coords: Vector2): Hex { - const x = coords.x - this.screenXOffset; - const y = coords.y - this.screenYOffset; - return Hex.fromPixel(new Vector2(x, y), this.hexSize); - } + public getScreenCoords(hex: Hex): Vector2 { + const coord = Hex.toPixel(hex, this.hexSize); + return new Vector2(coord.x + this.screenXOffset - this.screenCellWidth / 2, coord.y + this.screenYOffset - this.screenCellHeight / 2); + } - private drawBackground() { - const ctx = this.visMain.context; - const simLevel = this.simMain.currentLevel; - if (simLevel == null) { - return; - } + public getHexFromScreenCoords(coords: Vector2): Hex { + const x = coords.x - this.screenXOffset; + const y = coords.y - this.screenYOffset; + return Hex.fromPixel(new Vector2(x, y), this.hexSize); + } - const gdLevel = this.gdRoot.levels[simLevel.index]; - if (this.background == null) { - const backgroundCanvas = this.visMain.canvas.cloneNode() as HTMLCanvasElement; - const backgroundContext = backgroundCanvas.getContext("2d")!; - this.background = backgroundCanvas; - simLevel.cells.forEach((cell: SimCell) => { - if (cell.distance > gdLevel.radius) { - return; - } - if (cell.blockedType != -1 && cell.type == ECellType.Blocked) { - this.drawCellImage(backgroundContext, cell, "cell-blocked-" + (cell.blockedType | 0) + ".svg"); - } - }); + private drawBackground() { + const ctx = this.visMain.context; + const simLevel = this.simMain.currentLevel; + if (simLevel == null) { + return; + } - backgroundContext.globalCompositeOperation = "source-atop"; - backgroundContext.fillStyle = this.visMain.wallPattern; - backgroundContext.fillRect(0, 0, this.visMain.canvas.width, this.visMain.canvas.height); + const gdLevel = this.gdRoot.levels[simLevel.index]; + if (this.background == null) { + const backgroundCanvas = this.visMain.canvas.cloneNode() as HTMLCanvasElement; + const backgroundContext = backgroundCanvas.getContext('2d')!; + this.background = backgroundCanvas; + simLevel.cells.forEach((cell: SimCell) => { + if (cell.distance > gdLevel.radius) { + return; + } + if (cell.blockedType != -1 && cell.type == ECellType.Blocked) { + this.drawCellImage(backgroundContext, cell, 'cell-blocked-' + (cell.blockedType | 0) + '.svg'); + } + }); - const cellCanvas = this.visMain.canvas.cloneNode() as HTMLCanvasElement; - const cellContext = cellCanvas.getContext("2d")!; - simLevel.cells.forEach((cell: SimCell) => { - if (cell.distance > gdLevel.radius) { - return; - } - if (cell.type != ECellType.Entry) { - this.drawCellImage(cellContext, cell, "cell.svg"); - } - }); - backgroundContext.globalCompositeOperation = "destination-over"; - backgroundContext.drawImage(cellCanvas, 0, 0); - backgroundContext.globalCompositeOperation = "source-over"; - } + backgroundContext.globalCompositeOperation = 'source-atop'; + backgroundContext.fillStyle = this.visMain.wallPattern; + backgroundContext.fillRect(0, 0, this.visMain.canvas.width, this.visMain.canvas.height); - ctx.drawImage(this.background, 0, 0); - } + const cellCanvas = this.visMain.canvas.cloneNode() as HTMLCanvasElement; + const cellContext = cellCanvas.getContext('2d')!; + simLevel.cells.forEach((cell: SimCell) => { + if (cell.distance > gdLevel.radius) { + return; + } + if (cell.type != ECellType.Entry) { + this.drawCellImage(cellContext, cell, 'cell.svg'); + } + }); + backgroundContext.globalCompositeOperation = 'destination-over'; + backgroundContext.drawImage(cellCanvas, 0, 0); + backgroundContext.globalCompositeOperation = 'source-over'; + } - private drawProjectile(simProjectile: SimProjectile) { - const visProjectile = this.projectileMap.get(simProjectile); - if (!visProjectile) { - return; - } - const t = this.lastStep - Math.floor(this.lastStep); - const positions = visProjectile.positions; - if (!positions) { - return; - } - const pos = Vector2.lerp(positions[0], positions[1], t); - const width = this.screenCellWidth * simProjectile.size; - const height = this.screenCellHeight * simProjectile.size; - this.visMain.context.drawImage(this.assets.getImage("images/projectile.svg"), - this.screenXOffset + pos.x * this.hexSize - width / 2, - this.screenYOffset + pos.y * this.hexSize - height / 2, - width, - height); - } + ctx.drawImage(this.background, 0, 0); + } - private drawEnemy(simEnemy: SimEnemy) { - const visEnemy = this.enemyMap.get(simEnemy); - if (!visEnemy) { - return; - } - const t = this.lastStep - Math.floor(this.lastStep); - const positions = visEnemy.positions; - if (!positions) { - return; - } - const pos = Vector2.lerp(positions[0], positions[1], t); - this.visMain.context.drawImage( - visEnemy.image, - this.screenXOffset + pos.x * this.hexSize - this.screenCellWidth / 2, - this.screenYOffset + pos.y * this.hexSize - this.screenCellHeight / 2, - this.screenCellWidth, - this.screenCellHeight); - } + private drawProjectile(simProjectile: SimProjectile) { + const visProjectile = this.projectileMap.get(simProjectile); + if (!visProjectile) { + return; + } + const t = this.lastStep - Math.floor(this.lastStep); + const positions = visProjectile.positions; + if (!positions) { + return; + } + const pos = Vector2.lerp(positions[0], positions[1], t); + const width = this.screenCellWidth * simProjectile.size; + const height = this.screenCellHeight * simProjectile.size; + this.visMain.context.drawImage(this.assets.getImage('images/projectile.svg'), this.screenXOffset + pos.x * this.hexSize - width / 2, this.screenYOffset + pos.y * this.hexSize - height / 2, width, height); + } - private drawCell(cell: SimCell) { - const simLevel = this.simMain.currentLevel; - if (simLevel == null) { - return; - } + private drawEnemy(simEnemy: SimEnemy) { + const visEnemy = this.enemyMap.get(simEnemy); + if (!visEnemy) { + return; + } + const t = this.lastStep - Math.floor(this.lastStep); + const positions = visEnemy.positions; + if (!positions) { + return; + } + const pos = Vector2.lerp(positions[0], positions[1], t); + this.visMain.context.drawImage(visEnemy.image, this.screenXOffset + pos.x * this.hexSize - this.screenCellWidth / 2, this.screenYOffset + pos.y * this.hexSize - this.screenCellHeight / 2, this.screenCellWidth, this.screenCellHeight); + } - this.visMain.context.fillStyle = "rgba(192, 192, 192, 0.25)"; - if (cell.type == ECellType.Entry) { - this.drawCellImage(this.visMain.context, cell, "cell-entry-" + (cell.blockedType | 0) + ".svg"); - } + private drawCell(cell: SimCell) { + const simLevel = this.simMain.currentLevel; + if (simLevel == null) { + return; + } - const highlightedCell = simLevel.cells[simLevel.highlightedIndex]; - if (!!highlightedCell) { - let draw = highlightedCell.index == cell.index; - if (draw && highlightedCell.pathsToTarget != null) { - for (const routeIdx in highlightedCell.pathsToTarget) { - for (const idx in highlightedCell.pathsToTarget[routeIdx]) { - if (highlightedCell.pathsToTarget[routeIdx][idx] == highlightedCell.index) { - draw = true; - break; - } - } - } - } - if (draw) { - this.drawCellImage(this.visMain.context, highlightedCell, "cell-highlighted.svg"); - this.visMain.context.fillStyle = "rgba(0, 0, 0, 1)"; - } - } - if (cell.tower != null) { - this.drawCellImage(this.visMain.context, cell, "tower-" + (cell.tower.index | 0) + ".svg"); - } + this.visMain.context.fillStyle = 'rgba(192, 192, 192, 0.25)'; + if (cell.type == ECellType.Entry) { + this.drawCellImage(this.visMain.context, cell, 'cell-entry-' + (cell.blockedType | 0) + '.svg'); + } - const coords = this.getScreenCoords(cell.hex); - this.visMain.context.fillText("(" + cell.hex.col + ", " + cell.hex.row + ")", coords.x + 10, coords.y + this.screenCellHeight / 2 + 5); - } + const highlightedCell = simLevel.cells[simLevel.highlightedIndex]; + if (!!highlightedCell) { + let draw = highlightedCell.index == cell.index; + if (draw && highlightedCell.pathsToTarget != null) { + for (const routeIdx in highlightedCell.pathsToTarget) { + for (const idx in highlightedCell.pathsToTarget[routeIdx]) { + if (highlightedCell.pathsToTarget[routeIdx][idx] == highlightedCell.index) { + draw = true; + break; + } + } + } + } + if (draw) { + this.drawCellImage(this.visMain.context, highlightedCell, 'cell-highlighted.svg'); + this.visMain.context.fillStyle = 'rgba(0, 0, 0, 1)'; + } + } + if (cell.tower != null) { + this.drawCellImage(this.visMain.context, cell, 'tower-' + (cell.tower.index | 0) + '.svg'); + } - private drawCellImage(context: CanvasRenderingContext2D, cell: SimCell, name: string) { - const coords = this.getScreenCoords(cell.hex); - context.drawImage(this.assets.getImage("images/" + name), coords.x, coords.y, this.screenCellWidth, this.screenCellHeight); - } + const coords = this.getScreenCoords(cell.hex); + this.visMain.context.fillText('(' + cell.hex.col + ', ' + cell.hex.row + ')', coords.x + 10, coords.y + this.screenCellHeight / 2 + 5); + } + + private drawCellImage(context: CanvasRenderingContext2D, cell: SimCell, name: string) { + const coords = this.getScreenCoords(cell.hex); + context.drawImage(this.assets.getImage('images/' + name), coords.x, coords.y, this.screenCellWidth, this.screenCellHeight); + } } diff --git a/src/app/components/game/vis/VisMain.ts b/src/app/components/game/vis/VisMain.ts index 553d8df..30946b7 100644 --- a/src/app/components/game/vis/VisMain.ts +++ b/src/app/components/game/vis/VisMain.ts @@ -19,6 +19,7 @@ export class VisMain { private startTimestamp: number = 0; private ready: boolean = false; private gap: number = 0; + private animationFrameId: number | null = null; constructor(simMain: SimMain, assets: AssetPreloaderService, wrapper: HTMLDivElement, canvas: HTMLCanvasElement) { this.assets = assets; @@ -50,7 +51,7 @@ export class VisMain { return; } - requestAnimationFrame((timestamp: number) => { + this.animationFrameId = requestAnimationFrame((timestamp: number) => { this.step(timestamp); }); @@ -105,11 +106,17 @@ export class VisMain { stop() { this.active = false; + this.startTimestamp = 0; + this.visLevel.updateEveryFrame(-1); + if (this.animationFrameId !== null) { + cancelAnimationFrame(this.animationFrameId); + this.animationFrameId = null; + } } start() { this.active = true; - requestAnimationFrame((timestamp: number) => { + this.animationFrameId = requestAnimationFrame((timestamp: number) => { this.startTimestamp = timestamp - (this.simMain.currentStep / this.simMain.gdRoot.simulation.stepsPerSecond) * 1000; this.step(timestamp); });