From 8347190c703f4ca7f93c0b63bffccd2609306699 Mon Sep 17 00:00:00 2001 From: Evan Date: Sat, 21 Dec 2024 13:09:17 -0800 Subject: [PATCH] highlight human spawn --- TODO.txt | 7 +- src/client/graphics/layers/TerritoryLayer.ts | 68 +++++++++++++++++++- src/core/configuration/Config.ts | 1 + src/core/configuration/PastelTheme.ts | 6 ++ 4 files changed, 77 insertions(+), 5 deletions(-) diff --git a/TODO.txt b/TODO.txt index e3787997c..7ffe144c5 100644 --- a/TODO.txt +++ b/TODO.txt @@ -255,8 +255,11 @@ * make event box wider DONE 12/20/2024 * make attack bonus based on current attack size DONE 12/20/2024 * bug: ips are not stored DONE 12/20/2024 -* highlight player spawn +* highlight player spawn DONE 12/21/2024 +* show players joined username in private lobby +* make bots less likely to build ships * troop density affects attack bonus +* bugix: wait for css to load on front page * bug: NPCs don't have money * right click brings up player info menu * seperate server config from client config @@ -266,7 +269,6 @@ * UI/test too big on mobile * bug: build city 25k bump doesn't match troop/worker ratio * bug: mobile: if you don't have enough money can't get rid of build menu -* show players joined username in private lobby * have bots build cities & defense posts * allow longer names and allow them to be displayed in the Rank UI not be cut * make boats work on lakes @@ -288,7 +290,6 @@ * create perf test -* naval combat * revamp alliance system diff --git a/src/client/graphics/layers/TerritoryLayer.ts b/src/client/graphics/layers/TerritoryLayer.ts index dd8613c29..4d6f21e4e 100644 --- a/src/client/graphics/layers/TerritoryLayer.ts +++ b/src/client/graphics/layers/TerritoryLayer.ts @@ -1,8 +1,8 @@ import { PriorityQueue } from "@datastructures-js/priority-queue"; -import { Cell, Game, Player, Tile, TileEvent, UnitEvent, UnitType } from "../../../core/game/Game"; +import { Cell, Game, Player, PlayerType, Tile, TileEvent, UnitEvent, UnitType } from "../../../core/game/Game"; import { PseudoRandom } from "../../../core/PseudoRandom"; import { colord, Colord } from "colord"; -import { bfs, dist } from "../../../core/Util"; +import { bfs, dist, euclDist, euclideanDist } from "../../../core/Util"; import { Theme } from "../../../core/configuration/Config"; import { Layer } from "./Layer"; import { TransformHandler } from "../TransformHandler"; @@ -17,6 +17,11 @@ export class TerritoryLayer implements Layer { private random = new PseudoRandom(123) private theme: Theme = null + // Used for spawn highlighting + private highlightCanvas: HTMLCanvasElement + private highlightContext: CanvasRenderingContext2D + + constructor(private game: Game, eventBus: EventBus) { this.theme = game.config().theme() eventBus.on(TileEvent, e => this.tileUpdate(e)) @@ -27,6 +32,28 @@ export class TerritoryLayer implements Layer { } tick() { + if (!this.game.inSpawnPhase()) { + return + } + if (this.game.ticks() % 5 == 0) { + return + } + + this.highlightContext.clearRect(0, 0, this.game.width(), this.game.height()); + const humans = this.game.players() + .filter(p => p.type() == PlayerType.Human) + + const alreadyPainted = new Set() + for (const human of humans) { + for (const borderTile of human.borderTiles()) { + for (const neighbor of bfs(borderTile, euclDist(borderTile, 5))) { + if (!neighbor.hasOwner() && !alreadyPainted.has(neighbor)) { + this.paintHighlightCell(neighbor.cell(), this.theme.spawnHighlightColor(), 120) + alreadyPainted.add(neighbor) + } + } + } + } } init(game: Game) { @@ -38,6 +65,12 @@ export class TerritoryLayer implements Layer { this.canvas.width = this.game.width(); this.canvas.height = this.game.height(); this.context.putImageData(this.imageData, 0, 0); + + // Add a second canvas for highlights + this.highlightCanvas = document.createElement('canvas'); + this.highlightContext = this.highlightCanvas.getContext("2d", { alpha: true }); + this.highlightCanvas.width = this.game.width(); + this.highlightCanvas.height = this.game.height(); } initImageData() { @@ -51,6 +84,7 @@ export class TerritoryLayer implements Layer { renderLayer(context: CanvasRenderingContext2D) { this.renderTerritory() this.context.putImageData(this.imageData, 0, 0); + context.drawImage( this.canvas, -this.game.width() / 2, @@ -58,6 +92,15 @@ export class TerritoryLayer implements Layer { this.game.width(), this.game.height() ) + if (this.game.inSpawnPhase()) { + context.drawImage( + this.highlightCanvas, + -this.game.width() / 2, + -this.game.height() / 2, + this.game.width(), + this.game.height() + ); + } } renderTerritory() { @@ -137,9 +180,30 @@ export class TerritoryLayer implements Layer { tileUpdate(event: TileEvent) { this.enqueue(event.tile) + // if (this.game.inSpawnPhase()) { + // if (event.tile.owner().isPlayer()) { + // for (const border of (event.tile.owner() as Player).borderTiles()) { + // for (const neighbor of border.neighbors()) { + // if (!neighbor.hasOwner()) { + // this.paintHighlightCell(neighbor.cell(), this.theme.spawnHighlightColor(), 255) + // } + // } + // } + // } + // } } enqueue(tile: Tile) { this.tileToRenderQueue.push({ tile: tile, lastUpdate: this.game.ticks() + this.random.nextFloat(0, .5) }) } + + paintHighlightCell(cell: Cell, color: Colord, alpha: number) { + this.clearCell(cell) + this.highlightContext.fillStyle = color.alpha(alpha / 255).toRgbString(); + this.highlightContext.fillRect(cell.x, cell.y, 1, 1); + } + + clearHighlightCell(cell: Cell) { + this.highlightContext.clearRect(cell.x, cell.y, 1, 1); + } } \ No newline at end of file diff --git a/src/core/configuration/Config.ts b/src/core/configuration/Config.ts index 272ae4ce6..1b1fe8d46 100644 --- a/src/core/configuration/Config.ts +++ b/src/core/configuration/Config.ts @@ -88,5 +88,6 @@ export interface Theme { selfColor(): Colord allyColor(): Colord enemyColor(): Colord + spawnHighlightColor(): Colord } diff --git a/src/core/configuration/PastelTheme.ts b/src/core/configuration/PastelTheme.ts index 9b3ef29ec..06b80613b 100644 --- a/src/core/configuration/PastelTheme.ts +++ b/src/core/configuration/PastelTheme.ts @@ -126,6 +126,8 @@ export const pastelTheme = new class implements Theme { private _allyColor = colord({ r: 255, g: 255, b: 0 }) private _enemyColor = colord({ r: 255, g: 0, b: 0 }) + private _spawnHighlightColor = colord({ r: 255, g: 213, b: 79 }) + playerInfoColor(id: PlayerID): Colord { return colord({ r: 50, g: 50, b: 50 }) @@ -214,4 +216,8 @@ export const pastelTheme = new class implements Theme { enemyColor(): Colord { return this._enemyColor } + + spawnHighlightColor(): Colord { + return this._spawnHighlightColor + } } \ No newline at end of file