mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-06-29 21:52:12 +00:00
7a78e0c5a2
## Description: Add a visualization for how the current population is allocated. ## Please complete the following: - [ ] I have added screenshots for all UI updates - [x] I confirm I have thoroughly tested these changes and take full responsibility for any bugs introduced - [x] I understand that submitting code with bugs that could have been caught through manual testing blocks releases and new features for all contributors --------- Co-authored-by: Scott Anderson <662325+scottanderson@users.noreply.github.com> Co-authored-by: evanpelle <evanpelle@gmail.com>
102 lines
2.8 KiB
TypeScript
102 lines
2.8 KiB
TypeScript
import { GameMode, Team } from "../../../core/game/Game";
|
|
import { GameView } from "../../../core/game/GameView";
|
|
import { TransformHandler } from "../TransformHandler";
|
|
import { Layer } from "./Layer";
|
|
|
|
export class SpawnTimer implements Layer {
|
|
private ratios = [0];
|
|
private colors = ["rgba(0, 128, 255, 0.7)", "rgba(0, 0, 0, 0.5)"];
|
|
|
|
constructor(
|
|
private game: GameView,
|
|
private transformHandler: TransformHandler,
|
|
) {}
|
|
|
|
init() {}
|
|
|
|
tick() {
|
|
if (this.game.inSpawnPhase()) {
|
|
this.ratios[0] =
|
|
this.game.ticks() / this.game.config().numSpawnPhaseTurns();
|
|
return;
|
|
}
|
|
|
|
this.ratios = [];
|
|
this.colors = [];
|
|
|
|
if (this.game.config().gameConfig().gameMode !== GameMode.Team) {
|
|
const player = this.game.myPlayer();
|
|
if (player === null) return;
|
|
const max = this.game.config().maxPopulation(player);
|
|
const troops = player.troops();
|
|
const workers = player.workers();
|
|
const total = player.totalPopulation();
|
|
const attacking = total - troops - workers;
|
|
|
|
this.colors = [
|
|
"rgba(0, 128, 255, 0.7)",
|
|
"orange",
|
|
"red",
|
|
"rgba(0, 0, 0, 0.5)",
|
|
];
|
|
this.ratios = [workers / max, troops / max, attacking / max];
|
|
return;
|
|
}
|
|
|
|
const teamTiles: Map<Team, number> = new Map();
|
|
for (const player of this.game.players()) {
|
|
const team = player.team();
|
|
if (team === null) throw new Error("Team is null");
|
|
const tiles = teamTiles.get(team) ?? 0;
|
|
const sum = tiles + player.numTilesOwned();
|
|
teamTiles.set(team, sum);
|
|
}
|
|
|
|
const theme = this.game.config().theme();
|
|
const total = sumIterator(teamTiles.values());
|
|
if (total === 0) return;
|
|
for (const [team, count] of teamTiles) {
|
|
const ratio = count / total;
|
|
const color = theme.teamColor(team).toRgbString();
|
|
this.ratios.push(ratio);
|
|
this.colors.push(color);
|
|
}
|
|
}
|
|
|
|
shouldTransform(): boolean {
|
|
return false;
|
|
}
|
|
|
|
renderLayer(context: CanvasRenderingContext2D) {
|
|
if (this.ratios === null) return;
|
|
if (this.ratios.length === 0) return;
|
|
if (this.colors.length === 0) return;
|
|
|
|
const barHeight = 10;
|
|
const barWidth = this.transformHandler.width();
|
|
|
|
let x = 0;
|
|
let filledRatio = 0;
|
|
for (let i = 0; i < this.ratios.length && i < this.colors.length; i++) {
|
|
const ratio = this.ratios[i] ?? 1 - filledRatio;
|
|
const segmentWidth = barWidth * ratio;
|
|
|
|
context.fillStyle = this.colors[i];
|
|
context.fillRect(x, 0, segmentWidth, barHeight);
|
|
|
|
x += segmentWidth;
|
|
filledRatio += ratio;
|
|
}
|
|
}
|
|
}
|
|
|
|
function sumIterator(values: MapIterator<number>) {
|
|
// To use reduce, we'd need to allocate an array:
|
|
// return Array.from(values).reduce((sum, v) => sum + v, 0);
|
|
let total = 0;
|
|
for (const value of values) {
|
|
total += value;
|
|
}
|
|
return total;
|
|
}
|