sam is red when reloading (#268)

This commit is contained in:
Ilan Schemoul
2025-03-18 22:16:02 +01:00
committed by GitHub
parent a402242f11
commit 24f25d677a
10 changed files with 96 additions and 30 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 184 B

+52 -29
View File
@@ -6,6 +6,7 @@ import { EventBus } from "../../../core/EventBus";
import anchorIcon from "../../../../resources/images/buildings/port1.png";
import missileSiloIcon from "../../../../resources/images/buildings/silo1.png";
import SAMMissileIcon from "../../../../resources/images/buildings/silo4.png";
import SAMMissileReloadingIcon from "../../../../resources/images/buildings/silo4-reloading.png";
import shieldIcon from "../../../../resources/images/buildings/fortAlt2.png";
import cityIcon from "../../../../resources/images/buildings/cityAlt1.png";
import { GameView, UnitView } from "../../../core/game/GameView";
@@ -14,6 +15,7 @@ import { GameUpdateType } from "../../../core/game/GameUpdates";
import { euclDistFN } from "../../../core/game/GameMap";
const underConstructionColor = colord({ r: 150, g: 150, b: 150 });
const reloadingColor = colord({ r: 255, g: 0, b: 0 });
interface UnitRenderConfig {
icon: string;
@@ -41,17 +43,17 @@ export class StructureLayer implements Layer {
},
[UnitType.MissileSilo]: {
icon: missileSiloIcon,
borderRadius: 8,
borderRadius: 9.5,
territoryRadius: 6,
},
[UnitType.DefensePost]: {
icon: shieldIcon,
borderRadius: 8,
borderRadius: 9.5,
territoryRadius: 6,
},
[UnitType.SAMLauncher]: {
icon: SAMMissileIcon,
borderRadius: 8,
borderRadius: 10,
territoryRadius: 6,
},
};
@@ -62,32 +64,41 @@ export class StructureLayer implements Layer {
) {
this.theme = game.config().theme();
this.loadIconData();
this.loadIcon("reloadingSam", {
icon: SAMMissileReloadingIcon,
borderRadius: 8.525,
territoryRadius: 6.525,
});
}
private loadIcon(unitType: string, config: UnitRenderConfig) {
const image = new Image();
image.src = config.icon;
image.onload = () => {
// Create temporary canvas for icon processing
const tempCanvas = document.createElement("canvas");
const tempContext = tempCanvas.getContext("2d");
tempCanvas.width = image.width;
tempCanvas.height = image.height;
// Draw the unit icon
tempContext.drawImage(image, 0, 0);
const iconData = tempContext.getImageData(
0,
0,
tempCanvas.width,
tempCanvas.height,
);
this.unitIcons.set(unitType, iconData);
console.log(
`icond data width height: ${iconData.width}, ${iconData.height}`,
);
};
}
private loadIconData() {
Object.entries(this.unitConfigs).forEach(([unitType, config]) => {
const image = new Image();
image.src = config.icon;
image.onload = () => {
// Create temporary canvas for icon processing
const tempCanvas = document.createElement("canvas");
const tempContext = tempCanvas.getContext("2d");
tempCanvas.width = image.width;
tempCanvas.height = image.height;
// Draw the unit icon
tempContext.drawImage(image, 0, 0);
const iconData = tempContext.getImageData(
0,
0,
tempCanvas.width,
tempCanvas.height,
);
this.unitIcons.set(unitType, iconData);
console.log(
`icond data width height: ${iconData.width}, ${iconData.height}`,
);
};
this.loadIcon(unitType, config);
});
}
@@ -132,10 +143,17 @@ export class StructureLayer implements Layer {
private handleUnitRendering(unit: UnitView) {
const unitType = unit.constructionType() ?? unit.type();
let iconType = unitType;
if (!this.isUnitTypeSupported(unitType)) return;
const config = this.unitConfigs[unitType];
const icon = this.unitIcons.get(unitType);
let icon: ImageData;
if (unitType == UnitType.SAMLauncher && unit.isSamCooldown()) {
icon = this.unitIcons.get("reloadingSam");
} else {
icon = this.unitIcons.get(iconType);
}
if (!config || !icon) return;
@@ -151,6 +169,13 @@ export class StructureLayer implements Layer {
return;
}
let borderColor = this.theme.borderColor(unit.owner().info());
if (unitType == UnitType.SAMLauncher && unit.isSamCooldown()) {
borderColor = reloadingColor;
} else if (unit.type() == UnitType.Construction) {
borderColor = underConstructionColor;
}
// Draw border and territory
for (const tile of this.game.bfs(
unit.tile(),
@@ -158,9 +183,7 @@ export class StructureLayer implements Layer {
)) {
this.paintCell(
new Cell(this.game.x(tile), this.game.y(tile)),
unit.type() == UnitType.Construction
? underConstructionColor
: this.theme.borderColor(unit.owner().info()),
borderColor,
255,
);
}
+1
View File
@@ -170,6 +170,7 @@ export interface Config {
export interface Theme {
territoryColor(playerInfo: PlayerInfo): Colord;
specialBuildingColor(playerInfo: PlayerInfo): Colord;
borderColor(playerInfo: PlayerInfo): Colord;
defendedBorderColor(playerInfo: PlayerInfo): Colord;
terrainColor(gm: GameMap, tile: TileRef): Colord;
+9
View File
@@ -256,6 +256,15 @@ export const pastelTheme = new (class implements Theme {
return playerInfo.playerType == PlayerType.Human ? "#000000" : "#4D4D4D";
}
specialBuildingColor(playerInfo: PlayerInfo): Colord {
const tc = this.territoryColor(playerInfo).rgba;
return colord({
r: Math.max(tc.r - 50, 0),
g: Math.max(tc.g - 50, 0),
b: Math.max(tc.b - 50, 0),
});
}
borderColor(playerInfo: PlayerInfo): Colord {
const tc = this.territoryColor(playerInfo).rgba;
return colord({
@@ -256,6 +256,15 @@ export const pastelThemeDark = new (class implements Theme {
return playerInfo.playerType == PlayerType.Human ? "#ffffff" : "#e6e6e6";
}
specialBuildingColor(playerInfo: PlayerInfo): Colord {
const tc = this.territoryColor(playerInfo).rgba;
return colord({
r: Math.max(tc.r - 50, 0),
g: Math.max(tc.g - 50, 0),
b: Math.max(tc.b - 50, 0),
});
}
borderColor(playerInfo: PlayerInfo): Colord {
const tc = this.territoryColor(playerInfo).rgba;
return colord({
+8 -1
View File
@@ -92,8 +92,15 @@ export class SAMLauncherExecution implements Execution {
);
})[0] ?? null;
const cooldown =
this.lastMissileAttack != 0 &&
this.mg.ticks() - this.lastMissileAttack <= this.missileAttackRate;
if (this.post.isSamCooldown() != cooldown) {
this.post.setSamCooldown(cooldown);
}
if (this.target != null) {
if (this.mg.ticks() - this.lastMissileAttack > this.missileAttackRate) {
if (!this.post.isSamCooldown()) {
this.lastMissileAttack = this.mg.ticks();
this.mg.addExecution(
new SAMMissileExecution(
+2
View File
@@ -235,6 +235,8 @@ export interface Unit {
setWarshipTarget(target: Unit): void; // warship only
warshipTarget(): Unit;
setSamCooldown(isCoolingDown: boolean): void; // Only for sam
isSamCooldown(): boolean;
setDstPort(dstPort: Unit): void;
dstPort(): Unit; // Only for trade ships
detonationDst(): TileRef; // Only for nukes
+1
View File
@@ -74,6 +74,7 @@ export interface UnitUpdate {
warshipTargetId?: number;
health?: number;
constructionType?: UnitType;
isSamCooldown?: boolean;
}
export interface AttackUpdate {
+3
View File
@@ -111,6 +111,9 @@ export class UnitView {
}
return this.data.warshipTargetId;
}
isSamCooldown(): boolean {
return this.data.isSamCooldown;
}
}
export class PlayerView {
+11
View File
@@ -18,6 +18,7 @@ export class UnitImpl implements Unit {
private _constructionType: UnitType = undefined;
private _isSamCooldown: boolean;
private _dstPort: Unit | null = null; // Only for trade ships
private _detonationDst: TileRef | null = null; // Only for nukes
private _warshipTarget: Unit | null = null;
@@ -59,6 +60,7 @@ export class UnitImpl implements Unit {
dstPortId: dstPort ? dstPort.id() : null,
warshipTargetId: warshipTarget ? warshipTarget.id() : null,
detonationDst: this.detonationDst(),
isSamCooldown: this.isSamCooldown() ? this.isSamCooldown() : null,
};
}
@@ -182,6 +184,15 @@ export class UnitImpl implements Unit {
return this._dstPort;
}
setSamCooldown(cooldown: boolean): void {
this._isSamCooldown = cooldown;
this.mg.addUpdate(this.toUpdate());
}
isSamCooldown(): boolean {
return this._isSamCooldown;
}
setDstPort(dstPort: Unit): void {
this._dstPort = dstPort;
}