From 9717c95c34a5948240444caa3adb3937bb03a203 Mon Sep 17 00:00:00 2001 From: Doo <18369320+rldtech@users.noreply.github.com> Date: Fri, 13 Jun 2025 07:23:50 +0200 Subject: [PATCH] Update building images and adjust border/territory radii for unit configuration (#1037) ## Description: Implementing the new images for building with better quality: https://github.com/openfrontio/OpenFrontIO/issues/778 **Before :** ![image](https://github.com/user-attachments/assets/7ad756c5-f22f-4058-9153-59f6a0363382) **After :** ![image](https://github.com/user-attachments/assets/c5773420-336e-49c4-b8a1-8686c0bfc35b) ## Please complete the following: - [x] I have added screenshots for all UI updates - [x] I process any text displayed to the user through translateText() and I've added it to the en.json file - [x] I have added relevant tests to the test directory - [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 ## Please put your Discord username so you can be contacted if a bug or regression is found: .doo --------- Co-authored-by: rldtech Co-authored-by: tnhnblgl <51187395+tnhnblgl@users.noreply.github.com> Co-authored-by: evanpelle --- resources/images/buildings/cityAlt1.png | Bin 158 -> 2997 bytes resources/images/buildings/cityAlt1_old.png | Bin 0 -> 158 bytes resources/images/buildings/fortAlt2.png | Bin 128 -> 2991 bytes resources/images/buildings/fortAlt2_old.png | Bin 0 -> 128 bytes resources/images/buildings/port1.png | Bin 143 -> 2998 bytes resources/images/buildings/port1_old.png | Bin 0 -> 143 bytes .../images/buildings/silo1-reloading.png | Bin 157 -> 3202 bytes .../images/buildings/silo1-reloading_old.png | Bin 0 -> 157 bytes resources/images/buildings/silo1.png | Bin 139 -> 2965 bytes resources/images/buildings/silo1_old.png | Bin 0 -> 139 bytes .../images/buildings/silo4-reloading.png | Bin 184 -> 3179 bytes .../images/buildings/silo4-reloading_od.png | Bin 0 -> 184 bytes resources/images/buildings/silo4.png | Bin 158 -> 2967 bytes resources/images/buildings/silo4_old.png | Bin 0 -> 158 bytes src/client/graphics/layers/StructureLayer.ts | 156 +++++++++--------- 15 files changed, 78 insertions(+), 78 deletions(-) create mode 100644 resources/images/buildings/cityAlt1_old.png create mode 100644 resources/images/buildings/fortAlt2_old.png create mode 100644 resources/images/buildings/port1_old.png create mode 100644 resources/images/buildings/silo1-reloading_old.png create mode 100644 resources/images/buildings/silo1_old.png create mode 100644 resources/images/buildings/silo4-reloading_od.png create mode 100644 resources/images/buildings/silo4_old.png diff --git a/resources/images/buildings/cityAlt1.png b/resources/images/buildings/cityAlt1.png index c12b3bf94f9b0419f01bdc2d89a184e7f97dead3..0252904289d5ed9a3ea4b0b7863eee56b9abbb10 100644 GIT binary patch literal 2997 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 literal 143 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|JUv|;Lo9le z6D00Euorm{e7M8kxXa1SZB7=aRKs~uog-3Co7NiGnHi?o32Saknta%RVY*WcTe4|` oNQ0m$%VSwxtIX+qZF~$2j{od$b$?kV1T>Vv)78&qol`;+0E4_L1^@s6 diff --git a/resources/images/buildings/port1_old.png b/resources/images/buildings/port1_old.png new file mode 100644 index 0000000000000000000000000000000000000000..2341ba5a067fa14663d8b3bec7e031700205c17e GIT binary patch literal 143 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|JUv|;Lo9le z6D00Euorm{e7M8kxXa1SZB7=aRKs~uog-3Co7NiGnHi?o32Saknta%RVY*WcTe4|` oNQ0m$%VSwxtIX+qZF~$2j{od$b$?kV1T>Vv)78&qol`;+0E4_L1^@s6 literal 0 HcmV?d00001 diff --git a/resources/images/buildings/silo1-reloading.png b/resources/images/buildings/silo1-reloading.png index 28d1aef99096804326ba4d93094581f5c2dfa546..c8f804c78ba03d2f3b6796e7bf4d00ad1f1cbdaa 100644 GIT binary patch literal 3202 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 F1ONvBG;RO@ diff --git a/resources/images/buildings/silo1-reloading_old.png b/resources/images/buildings/silo1-reloading_old.png new file mode 100644 index 0000000000000000000000000000000000000000..28d1aef99096804326ba4d93094581f5c2dfa546 GIT binary patch literal 157 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`DV{ElAr}70DGLM)f>z8=?2z~n z=JwS7%<4n_?-uNswLsiqmgB61wh1W=KE`LtO6)vj4zuo<)9q{A#<(QwSSG_J`@)+% zpT({@sE8Dt=;Tk=dC+Y&iN~Se?8_2=16hGn+RXV3406mig2krW&jama@O1TaS?83{ F1ONvBG;RO@ literal 0 HcmV?d00001 diff --git a/resources/images/buildings/silo1.png b/resources/images/buildings/silo1.png index 01019f0f868c377de7a9665f99f2df2b27ec1854..66342084f7ccc4e37f48f4651e42dc8dc4ac396d 100644 GIT binary patch literal 2965 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 diff --git a/resources/images/buildings/silo1_old.png b/resources/images/buildings/silo1_old.png new file mode 100644 index 0000000000000000000000000000000000000000..01019f0f868c377de7a9665f99f2df2b27ec1854 GIT binary patch literal 139 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|Ts>VJLo9le z6C_xBj%fV)|Nnpe4mLM85nG=l8E)5IOdPgJO3N=-lUT4mErt2Sr5;~lGvEP((3 literal 0 HcmV?d00001 diff --git a/resources/images/buildings/silo4-reloading.png b/resources/images/buildings/silo4-reloading.png index f7c22aa90848d789379eb98b0fb985dfc8e1f0f8..0ed00d6cc76ea6892afc2eb7d0ce30dbb7b514f2 100755 GIT binary patch literal 3179 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 RdR+hj002ovPDHLkV1gj){0{&C literal 184 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|iacE$LoED{ zPCm$YK!L;A{n7vWjh)==Vn@UxZC-@_%HTXv{G;Wid-mb~p6@r9vCi;F+|S@~K;gnc z!2{j7e34U*HZooin7CO)z&fAtqTMDr#mUXP8}5E7)ec;u&osL(rnL1(8ux;tXpsQH g=-#6XkB7AG)rgrRcp&7FE6{cZPgg&ebxsLQ0H0bzbN~PV diff --git a/resources/images/buildings/silo4-reloading_od.png b/resources/images/buildings/silo4-reloading_od.png new file mode 100644 index 0000000000000000000000000000000000000000..f7c22aa90848d789379eb98b0fb985dfc8e1f0f8 GIT binary patch literal 184 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|iacE$LoED{ zPCm$YK!L;A{n7vWjh)==Vn@UxZC-@_%HTXv{G;Wid-mb~p6@r9vCi;F+|S@~K;gnc z!2{j7e34U*HZooin7CO)z&fAtqTMDr#mUXP8}5E7)ec;u&osL(rnL1(8ux;tXpsQH g=-#6XkB7AG)rgrRcp&7FE6{cZPgg&ebxsLQ0H0bzbN~PV literal 0 HcmV?d00001 diff --git a/resources/images/buildings/silo4.png b/resources/images/buildings/silo4.png index fc37c4694a6c16ebf075e3eeb899f9617dd75275..bd9709e0e1e2d5437ba4a36bf7f2a63fac0bbaeb 100644 GIT binary patch literal 2967 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 GGywq0c{k<& diff --git a/resources/images/buildings/silo4_old.png b/resources/images/buildings/silo4_old.png new file mode 100644 index 0000000000000000000000000000000000000000..fc37c4694a6c16ebf075e3eeb899f9617dd75275 GIT binary patch literal 158 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|B0OCjLo9mN z1{n%5C~%xw_rHGTG_kiAERuCxT#jcPy1~w1u}JdiG^Riwt#vNTmaHi|?)a?9s^YAI z>_I-GbHUfo_*x&Sk6v*pJvoN&is`x^3-0X^o{;~K-Han3eV@tJRc=5#7(8A5T-G@y GGywq0c{k<& literal 0 HcmV?d00001 diff --git a/src/client/graphics/layers/StructureLayer.ts b/src/client/graphics/layers/StructureLayer.ts index 180e838ab..0ae34d5a2 100644 --- a/src/client/graphics/layers/StructureLayer.ts +++ b/src/client/graphics/layers/StructureLayer.ts @@ -27,6 +27,11 @@ const underConstructionColor = colord({ r: 150, g: 150, b: 150 }); const reloadingColor = colord({ r: 255, g: 0, b: 0 }); const selectedUnitColor = colord({ r: 0, g: 255, b: 255 }); +// Base radius values and scaling factor for unit borders and territories +const BASE_BORDER_RADIUS = 16.5; +const BASE_TERRITORY_RADIUS = 13.5; +const RADIUS_SCALE_FACTOR = 0.5; + type DistanceFunction = typeof euclDistFN; enum UnitBorderType { @@ -46,41 +51,43 @@ interface UnitRenderConfig { export class StructureLayer implements Layer { private canvas: HTMLCanvasElement; private context: CanvasRenderingContext2D; - private unitIcons: Map = new Map(); + private unitIcons: Map = new Map(); private theme: Theme; private selectedStructureUnit: UnitView | null = null; private previouslySelected: UnitView | null = null; + private tempCanvas: HTMLCanvasElement; + private tempContext: CanvasRenderingContext2D; // Configuration for supported unit types only private readonly unitConfigs: Partial> = { [UnitType.Port]: { icon: anchorIcon, - borderRadius: 8.525, - territoryRadius: 6.525, + borderRadius: BASE_BORDER_RADIUS * RADIUS_SCALE_FACTOR, + territoryRadius: BASE_TERRITORY_RADIUS * RADIUS_SCALE_FACTOR, borderType: UnitBorderType.Round, }, [UnitType.City]: { icon: cityIcon, - borderRadius: 8.525, - territoryRadius: 6.525, + borderRadius: BASE_BORDER_RADIUS * RADIUS_SCALE_FACTOR, + territoryRadius: BASE_TERRITORY_RADIUS * RADIUS_SCALE_FACTOR, borderType: UnitBorderType.Round, }, [UnitType.MissileSilo]: { icon: missileSiloIcon, - borderRadius: 8.525, - territoryRadius: 6.525, + borderRadius: BASE_BORDER_RADIUS * RADIUS_SCALE_FACTOR, + territoryRadius: BASE_TERRITORY_RADIUS * RADIUS_SCALE_FACTOR, borderType: UnitBorderType.Square, }, [UnitType.DefensePost]: { icon: shieldIcon, - borderRadius: 8.525, - territoryRadius: 6.525, + borderRadius: BASE_BORDER_RADIUS * RADIUS_SCALE_FACTOR, + territoryRadius: BASE_TERRITORY_RADIUS * RADIUS_SCALE_FACTOR, borderType: UnitBorderType.Hexagon, }, [UnitType.SAMLauncher]: { icon: SAMMissileIcon, - borderRadius: 8.525, - territoryRadius: 6.525, + borderRadius: BASE_BORDER_RADIUS * RADIUS_SCALE_FACTOR, + territoryRadius: BASE_TERRITORY_RADIUS * RADIUS_SCALE_FACTOR, borderType: UnitBorderType.Square, }, }; @@ -98,17 +105,21 @@ export class StructureLayer implements Layer { } this.unitInfoModal = unitInfoModal; this.theme = game.config().theme(); + this.tempCanvas = document.createElement("canvas"); + const tempContext = this.tempCanvas.getContext("2d"); + if (tempContext === null) throw new Error("2d context not supported"); + this.tempContext = tempContext; this.loadIconData(); this.loadIcon("reloadingSam", { icon: SAMMissileReloadingIcon, - borderRadius: 8.525, - territoryRadius: 6.525, + borderRadius: BASE_BORDER_RADIUS * RADIUS_SCALE_FACTOR, + territoryRadius: BASE_TERRITORY_RADIUS * RADIUS_SCALE_FACTOR, borderType: UnitBorderType.Square, }); this.loadIcon("reloadingSilo", { icon: MissileSiloReloadingIcon, - borderRadius: 8.525, - territoryRadius: 6.525, + borderRadius: BASE_BORDER_RADIUS * RADIUS_SCALE_FACTOR, + territoryRadius: BASE_TERRITORY_RADIUS * RADIUS_SCALE_FACTOR, borderType: UnitBorderType.Square, }); } @@ -117,26 +128,14 @@ export class StructureLayer implements Layer { 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"); - if (tempContext === null) throw new Error("2d context not supported"); - 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); + this.unitIcons.set(unitType, image); console.log( - `icon data width height: ${iconData.width}, ${iconData.height}`, + `icon loaded: ${unitType}, size: ${image.width}x${image.height}`, ); }; + image.onerror = () => { + console.error(`Failed to load icon for ${unitType}: ${config.icon}`); + }; } private loadIconData() { @@ -170,8 +169,13 @@ export class StructureLayer implements Layer { const context = this.canvas.getContext("2d", { alpha: true }); if (context === null) throw new Error("2d context not supported"); this.context = context; - this.canvas.width = this.game.width(); - this.canvas.height = this.game.height(); + + // Enable smooth scaling + this.context.imageSmoothingEnabled = true; + this.context.imageSmoothingQuality = "high"; + + this.canvas.width = this.game.width() * 2; + this.canvas.height = this.game.height() * 2; this.game.units().forEach((u) => this.handleUnitRendering(u)); } @@ -240,16 +244,19 @@ export class StructureLayer implements Layer { if (!this.isUnitTypeSupported(unitType)) return; const config = this.unitConfigs[unitType]; - let icon: ImageData | undefined; + let icon: HTMLImageElement | undefined; + let borderColor = this.theme.borderColor(unit.owner()); + // Handle cooldown states and special icons if (unitType === UnitType.SAMLauncher && unit.isInCooldown()) { icon = this.unitIcons.get("reloadingSam"); - } else { - icon = this.unitIcons.get(iconType); - } - - if (unitType === UnitType.MissileSilo && unit.isInCooldown()) { + borderColor = reloadingColor; + } else if (unitType === UnitType.MissileSilo && unit.isInCooldown()) { icon = this.unitIcons.get("reloadingSilo"); + borderColor = reloadingColor; + } else if (unit.type() === UnitType.Construction) { + icon = this.unitIcons.get(iconType); + borderColor = underConstructionColor; } else { icon = this.unitIcons.get(iconType); } @@ -267,33 +274,23 @@ export class StructureLayer implements Layer { if (!unit.isActive()) return; - let borderColor = this.theme.borderColor(unit.owner()); - if (unitType === UnitType.SAMLauncher && unit.isInCooldown()) { - borderColor = reloadingColor; - } else if (unit.type() === UnitType.Construction) { - borderColor = underConstructionColor; - } - - if (unitType === UnitType.MissileSilo && unit.isInCooldown()) { - borderColor = reloadingColor; - } else if (unit.type() === UnitType.Construction) { - borderColor = underConstructionColor; - } - if (this.selectedStructureUnit === unit) { borderColor = selectedUnitColor; } this.drawBorder(unit, borderColor, config, drawFunction); - const startX = this.game.x(unit.tile()) - Math.floor(icon.width / 2); - const startY = this.game.y(unit.tile()) - Math.floor(icon.height / 2); - // Draw the icon - this.renderIcon(icon, startX, startY, icon.width, icon.height, unit); + // Render icon at 1/2 scale for better quality + const scaledWidth = icon.width >> 1; + const scaledHeight = icon.height >> 1; + const startX = this.game.x(unit.tile()) - (scaledWidth >> 1); + const startY = this.game.y(unit.tile()) - (scaledHeight >> 1); + + this.renderIcon(icon, startX, startY, scaledWidth, scaledHeight, unit); } private renderIcon( - iconData: ImageData, + image: HTMLImageElement, startX: number, startY: number, width: number, @@ -304,36 +301,39 @@ export class StructureLayer implements Layer { if (unit.type() === UnitType.Construction) { color = underConstructionColor; } - for (let y = 0; y < height; y++) { - for (let x = 0; x < width; x++) { - const iconIndex = (y * width + x) * 4; - const alpha = iconData.data[iconIndex + 3]; - if (alpha > 0) { - const targetX = startX + x; - const targetY = startY + y; + // Make temp canvas at the final render size (2x scale) + this.tempCanvas.width = width * 2; + this.tempCanvas.height = height * 2; - if ( - targetX >= 0 && - targetX < this.game.width() && - targetY >= 0 && - targetY < this.game.height() - ) { - this.paintCell(new Cell(targetX, targetY), color, alpha); - } - } - } - } + // Enable smooth scaling + this.tempContext.imageSmoothingEnabled = true; + this.tempContext.imageSmoothingQuality = "high"; + + // Draw the image at final size with high quality scaling + this.tempContext.drawImage(image, 0, 0, width * 2, height * 2); + + // Apply color tinting using multiply blend mode + this.tempContext.globalCompositeOperation = "multiply"; + this.tempContext.fillStyle = color.toRgbString(); + this.tempContext.fillRect(0, 0, width * 2, height * 2); + + // Restore the alpha channel + this.tempContext.globalCompositeOperation = "destination-in"; + this.tempContext.drawImage(image, 0, 0, width * 2, height * 2); + + // Draw the final result to the main canvas + this.context.drawImage(this.tempCanvas, startX * 2, startY * 2); } paintCell(cell: Cell, color: Colord, alpha: number) { this.clearCell(cell); this.context.fillStyle = color.alpha(alpha / 255).toRgbString(); - this.context.fillRect(cell.x, cell.y, 1, 1); + this.context.fillRect(cell.x * 2, cell.y * 2, 2, 2); } clearCell(cell: Cell) { - this.context.clearRect(cell.x, cell.y, 1, 1); + this.context.clearRect(cell.x * 2, cell.y * 2, 2, 2); } private findStructureUnitAtCell(