thread_split: convert all tile to tileref

This commit is contained in:
Evan
2025-02-01 12:05:11 -08:00
parent c42cc2a9b4
commit f0f5bae79f
53 changed files with 1101 additions and 1402 deletions
+211 -87
View File
@@ -1,12 +1,12 @@
import { Colord } from "colord";
import { Theme } from "../../../core/configuration/Config";
import { Unit, Cell, Game, Tile, UnitType, Player, UnitUpdate } from "../../../core/game/Game";
import { bfs, dist, euclDist } from "../../../core/Util";
import { Unit, UnitType, Player, UnitUpdate } from "../../../core/game/Game";
import { Layer } from "./Layer";
import { EventBus } from "../../../core/EventBus";
import { AlternateViewEvent } from "../../InputHandler";
import { ClientID } from "../../../core/Schemas";
import { GameView } from "../../../core/GameView";
import { euclDistFN, manhattanDistFN, TileRef } from "../../../core/game/GameMap";
enum Relationship {
Self,
@@ -18,15 +18,15 @@ export class UnitLayer implements Layer {
private canvas: HTMLCanvasElement;
private context: CanvasRenderingContext2D;
private boatToTrail = new Map<Unit, Set<Tile>>();
private boatToTrail = new Map<Unit, Set<TileRef>>();
private theme: Theme = null;
private alternateView = false
private alternateView = false;
private myPlayer: Player | null = null
private myPlayer: Player | null = null;
private oldShellTile = new Map<Unit, Tile>()
private oldShellTile = new Map<Unit, TileRef>();
constructor(private game: GameView, private eventBus: EventBus, private clientID: ClientID) {
this.theme = game.config().theme();
@@ -38,17 +38,17 @@ export class UnitLayer implements Layer {
tick() {
if (this.myPlayer == null) {
this.myPlayer = this.game.playerByClientID(this.clientID)
this.myPlayer = this.game.playerByClientID(this.clientID);
}
for (const unit of this.game.units()) {
if (unit.wasUpdated())
this.onUnitEvent(unit)
this.onUnitEvent(unit);
}
}
init() {
this.eventBus.on(AlternateViewEvent, e => this.onAlternativeViewEvent(e))
this.redraw()
this.eventBus.on(AlternateViewEvent, e => this.onAlternativeViewEvent(e));
this.redraw();
}
renderLayer(context: CanvasRenderingContext2D) {
@@ -62,11 +62,10 @@ export class UnitLayer implements Layer {
}
onAlternativeViewEvent(event: AlternateViewEvent) {
this.alternateView = event.alternateView
this.redraw()
this.alternateView = event.alternateView;
this.redraw();
}
redraw() {
this.canvas = document.createElement('canvas');
this.context = this.canvas.getContext("2d");
@@ -80,15 +79,15 @@ export class UnitLayer implements Layer {
private relationship(unit: Unit): Relationship {
if (this.myPlayer == null) {
return Relationship.Enemy
return Relationship.Enemy;
}
if (this.myPlayer == unit.owner()) {
return Relationship.Self
return Relationship.Self;
}
if (this.myPlayer.isAlliedWith(unit.owner())) {
return Relationship.Ally
return Relationship.Ally;
}
return Relationship.Enemy
return Relationship.Enemy;
}
onUnitEvent(unit: Unit) {
@@ -103,137 +102,262 @@ export class UnitLayer implements Layer {
this.handleBattleshipEvent(unit);
break;
case UnitType.Shell:
this.handleShellEvent(unit)
this.handleShellEvent(unit);
break;
case UnitType.TradeShip:
this.handleTradeShipEvent(unit)
this.handleTradeShipEvent(unit);
break;
case UnitType.AtomBomb:
case UnitType.HydrogenBomb:
this.handleNuke(unit)
break
this.handleNuke(unit);
break;
}
}
private handleDestroyerEvent(unit: Unit) {
const rel = this.relationship(unit)
bfs(unit.lastTile(), euclDist(unit.lastTile(), 4)).forEach(t => {
this.clearCell(t.cell());
});
const rel = this.relationship(unit);
// Clear previous area
for (const t of this.game.bfs(unit.lastTile(), euclDistFN(unit.lastTile(), 4))) {
this.clearCell(this.game.x(t), this.game.y(t));
}
if (!unit.isActive()) {
return
return;
}
// Paint border
for (const t of this.game.bfs(unit.tile(), euclDistFN(unit.tile(), 4))) {
this.paintCell(
this.game.x(t),
this.game.y(t),
rel,
this.theme.borderColor(unit.owner().info()),
255
);
}
// Paint territory
for (const t of this.game.bfs(unit.tile(), manhattanDistFN(unit.tile(), 3))) {
this.paintCell(
this.game.x(t),
this.game.y(t),
rel,
this.theme.territoryColor(unit.owner().info()),
255
);
}
bfs(unit.tile(), euclDist(unit.tile(), 4))
.forEach(t => this.paintCell(t.cell(), rel, this.theme.borderColor(unit.owner().info()), 255));
bfs(unit.tile(), dist(unit.tile(), 3))
.forEach(t => this.paintCell(t.cell(), rel, this.theme.territoryColor(unit.owner().info()), 255));
}
private handleBattleshipEvent(unit: Unit) {
const rel = this.relationship(unit)
bfs(unit.lastTile(), euclDist(unit.lastTile(), 6)).forEach(t => {
this.clearCell(t.cell());
});
const rel = this.relationship(unit);
// Clear previous area
for (const t of this.game.bfs(unit.lastTile(), euclDistFN(unit.lastTile(), 6))) {
this.clearCell(this.game.x(t), this.game.y(t));
}
if (!unit.isActive()) {
return
return;
}
// Paint outer territory
for (const t of this.game.bfs(unit.tile(), euclDistFN(unit.tile(), 5))) {
this.paintCell(
this.game.x(t),
this.game.y(t),
rel,
this.theme.territoryColor(unit.owner().info()),
255
);
}
// Paint border
for (const t of this.game.bfs(unit.tile(), manhattanDistFN(unit.tile(), 4))) {
this.paintCell(
this.game.x(t),
this.game.y(t),
rel,
this.theme.borderColor(unit.owner().info()),
255
);
}
// Paint inner territory
for (const t of this.game.bfs(unit.tile(), euclDistFN(unit.tile(), 1))) {
this.paintCell(
this.game.x(t),
this.game.y(t),
rel,
this.theme.territoryColor(unit.owner().info()),
255
);
}
bfs(unit.tile(), euclDist(unit.tile(), 5))
.forEach(t => this.paintCell(t.cell(), rel, this.theme.territoryColor(unit.owner().info()), 255));
bfs(unit.tile(), dist(unit.tile(), 4))
.forEach(t => this.paintCell(t.cell(), rel, this.theme.borderColor(unit.owner().info()), 255));
bfs(unit.tile(), euclDist(unit.tile(), 1))
.forEach(t => this.paintCell(t.cell(), rel, this.theme.territoryColor(unit.owner().info()), 255));
}
private handleShellEvent(unit: Unit) {
const rel = this.relationship(unit)
const rel = this.relationship(unit);
this.clearCell(unit.lastTile().cell())
// Clear current and previous positions
this.clearCell(this.game.x(unit.lastTile()), this.game.y(unit.lastTile()));
if (this.oldShellTile.has(unit)) {
this.clearCell(this.oldShellTile.get(unit).cell())
const oldTile = this.oldShellTile.get(unit);
this.clearCell(this.game.x(oldTile), this.game.y(oldTile));
}
this.oldShellTile.set(unit, unit.lastTile())
this.oldShellTile.set(unit, unit.lastTile());
if (!unit.isActive()) {
return
return;
}
this.paintCell(unit.tile().cell(), rel, this.theme.borderColor(unit.owner().info()), 255)
this.paintCell(unit.lastTile().cell(), rel, this.theme.borderColor(unit.owner().info()), 255)
// Paint current and previous positions
this.paintCell(
this.game.x(unit.tile()),
this.game.y(unit.tile()),
rel,
this.theme.borderColor(unit.owner().info()),
255
);
this.paintCell(
this.game.x(unit.lastTile()),
this.game.y(unit.lastTile()),
rel,
this.theme.borderColor(unit.owner().info()),
255
);
}
private handleNuke(unit: Unit) {
const rel = this.relationship(unit)
bfs(unit.lastTile(), euclDist(unit.lastTile(), 2)).forEach(t => {
this.clearCell(t.cell());
});
if (unit.isActive()) {
bfs(unit.tile(), euclDist(unit.tile(), 2))
.forEach(t => this.paintCell(t.cell(), rel, this.theme.borderColor(unit.owner().info()), 255));
const rel = this.relationship(unit);
// Clear previous area
for (const t of this.game.bfs(unit.lastTile(), euclDistFN(unit.lastTile(), 2))) {
this.clearCell(this.game.x(t), this.game.y(t));
}
if (unit.isActive()) {
// Paint area
for (const t of this.game.bfs(unit.tile(), euclDistFN(unit.tile(), 2))) {
this.paintCell(
this.game.x(t),
this.game.y(t),
rel,
this.theme.borderColor(unit.owner().info()),
255
);
}
}
}
private handleTradeShipEvent(unit: Unit) {
const rel = this.relationship(unit)
bfs(unit.lastTile(), euclDist(unit.lastTile(), 3)).forEach(t => {
this.clearCell(t.cell());
});
if (unit.isActive()) {
bfs(unit.tile(), dist(unit.tile(), 2))
.forEach(t => this.paintCell(t.cell(), rel, this.theme.territoryColor(unit.owner().info()), 255));
const rel = this.relationship(unit);
// Clear previous area
for (const t of this.game.bfs(unit.lastTile(), euclDistFN(unit.lastTile(), 3))) {
this.clearCell(this.game.x(t), this.game.y(t));
}
if (unit.isActive()) {
bfs(unit.tile(), dist(unit.tile(), 1))
.forEach(t => this.paintCell(t.cell(), rel, this.theme.borderColor(unit.owner().info()), 255));
// Paint territory
for (const t of this.game.bfs(unit.tile(), manhattanDistFN(unit.tile(), 2))) {
this.paintCell(
this.game.x(t),
this.game.y(t),
rel,
this.theme.territoryColor(unit.owner().info()),
255
);
}
// Paint border
for (const t of this.game.bfs(unit.tile(), manhattanDistFN(unit.tile(), 1))) {
this.paintCell(
this.game.x(t),
this.game.y(t),
rel,
this.theme.borderColor(unit.owner().info()),
255
);
}
}
}
private handleBoatEvent(unit: Unit) {
const rel = this.relationship(unit)
const rel = this.relationship(unit);
if (!this.boatToTrail.has(unit)) {
this.boatToTrail.set(unit, new Set<Tile>());
this.boatToTrail.set(unit, new Set<TileRef>());
}
const trail = this.boatToTrail.get(unit);
trail.add(unit.lastTile());
bfs(unit.lastTile(), dist(unit.lastTile(), 3)).forEach(t => {
this.clearCell(t.cell());
});
// Clear previous area
for (const t of this.game.bfs(unit.lastTile(), manhattanDistFN(unit.lastTile(), 3))) {
this.clearCell(this.game.x(t), this.game.y(t));
}
if (unit.isActive()) {
// Paint trail
for (const t of trail) {
this.paintCell(t.cell(), rel, this.theme.territoryColor(unit.owner().info()), 150);
this.paintCell(
this.game.x(t),
this.game.y(t),
rel,
this.theme.territoryColor(unit.owner().info()),
150
);
}
// Paint border
for (const t of this.game.bfs(unit.tile(), manhattanDistFN(unit.tile(), 2))) {
this.paintCell(
this.game.x(t),
this.game.y(t),
rel,
this.theme.borderColor(unit.owner().info()),
255
);
}
// Paint territory
for (const t of this.game.bfs(unit.tile(), manhattanDistFN(unit.tile(), 1))) {
this.paintCell(
this.game.x(t),
this.game.y(t),
rel,
this.theme.territoryColor(unit.owner().info()),
255
);
}
bfs(unit.tile(), dist(unit.tile(), 2))
.forEach(t => this.paintCell(t.cell(), rel, this.theme.borderColor(unit.owner().info()), 255));
bfs(unit.tile(), dist(unit.tile(), 1))
.forEach(t => this.paintCell(t.cell(), rel, this.theme.territoryColor(unit.owner().info()), 255));
} else {
trail.forEach(t => this.clearCell(t.cell()));
for (const t of trail) {
this.clearCell(this.game.x(t), this.game.y(t));
}
this.boatToTrail.delete(unit);
}
}
paintCell(cell: Cell, relationship: Relationship, color: Colord, alpha: number) {
this.clearCell(cell)
paintCell(x: number, y: number, relationship: Relationship, color: Colord, alpha: number) {
this.clearCell(x, y);
if (this.alternateView) {
switch (relationship) {
case Relationship.Self:
this.context.fillStyle = this.theme.selfColor().toRgbString()
break
this.context.fillStyle = this.theme.selfColor().toRgbString();
break;
case Relationship.Ally:
this.context.fillStyle = this.theme.allyColor().toRgbString()
break
this.context.fillStyle = this.theme.allyColor().toRgbString();
break;
case Relationship.Enemy:
this.context.fillStyle = this.theme.enemyColor().toRgbString()
break
this.context.fillStyle = this.theme.enemyColor().toRgbString();
break;
}
} else {
this.context.fillStyle = color.alpha(alpha / 255).toRgbString();
}
this.context.fillRect(cell.x, cell.y, 1, 1);
this.context.fillRect(x, y, 1, 1);
}
clearCell(cell: Cell) {
this.context.clearRect(cell.x, cell.y, 1, 1);
clearCell(x: number, y: number) {
this.context.clearRect(x, y, 1, 1);
}
}