diff --git a/src/client/graphics/layers/StructureDrawingUtils.ts b/src/client/graphics/layers/StructureDrawingUtils.ts index 09ac75814..ad1496dfa 100644 --- a/src/client/graphics/layers/StructureDrawingUtils.ts +++ b/src/client/graphics/layers/StructureDrawingUtils.ts @@ -253,26 +253,13 @@ export class SpriteFactory { structureCanvas.height = Math.ceil(iconSize); const context = structureCanvas.getContext("2d")!; - const tc = owner.territoryColor(); - const bc = owner.borderColor(); - - // Potentially change logic here. Some TC/BC combinations do not provide good color contrast. - const darker = bc.luminance() < tc.luminance() ? bc : tc; - const lighter = bc.luminance() < tc.luminance() ? tc : bc; - - let borderColor: string; - if (isConstruction) { - context.fillStyle = "rgb(198, 198, 198)"; - borderColor = "rgb(128, 127, 127)"; - } else { - context.fillStyle = lighter - .lighten(0.13) - .alpha(renderIcon ? 0.65 : 1) - .toRgbString(); - const darken = darker.isLight() ? 0.17 : 0.15; - borderColor = darker.darken(darken).toRgbString(); - } - context.strokeStyle = borderColor; + // Use structureColors defined from the PlayerView. + context.fillStyle = isConstruction + ? "rgb(198,198,198)" + : owner.structureColors().light.toRgbString(); + context.strokeStyle = isConstruction + ? "rgb(127,127, 127)" + : owner.structureColors().dark.toRgbString(); context.lineWidth = 1; const halfIconSize = iconSize / 2; @@ -400,7 +387,10 @@ export class SpriteFactory { }; const [offsetX, offsetY] = SHAPE_OFFSETS[shape] || [0, 0]; context.drawImage( - this.getImageColored(structureInfo.image, borderColor), + this.getImageColored( + structureInfo.image, + owner.structureColors().dark.toRgbString(), + ), offsetX, offsetY, ); diff --git a/src/core/configuration/Colors.ts b/src/core/configuration/Colors.ts index 7de52c3b0..f90b034fb 100644 --- a/src/core/configuration/Colors.ts +++ b/src/core/configuration/Colors.ts @@ -42,222 +42,174 @@ function generateTeamColors(baseColor: Colord): Colord[] { } export const nationColors: Colord[] = [ + colord("rgb(210,210,100)"), // Lime Yellow + colord("rgb(180,210,120)"), // Light Green + colord("rgb(170,190,100)"), // Yellow Green + colord("rgb(80,200,120)"), // Emerald Green + colord("rgb(130,200,130)"), // Light Sea Green + colord("rgb(140,180,140)"), // Dark Sea Green + colord("rgb(160,190,160)"), // Pale Green + colord("rgb(160,180,140)"), // Dark Olive Green + colord("rgb(100,160,80)"), // Olive Green + colord("rgb(100,140,110)"), // Sea Green + colord("rgb(100,180,160)"), // Aquamarine + colord("rgb(130,180,170)"), // Medium Aquamarine + colord("rgb(170,190,180)"), // Pale Blue Green + colord("rgb(100,130,150)"), // Steel Blue + colord("rgb(120,160,200)"), // Cornflower Blue + colord("rgb(140,150,180)"), // Light Slate Gray + colord("rgb(100,210,210)"), // Turquoise + colord("rgb(140,180,220)"), // Light Blue + colord("rgb(130,170,190)"), // Cadet Blue + colord("rgb(100,180,230)"), // Sky Blue + colord("rgb(80,130,190)"), // Navy Blue + colord("rgb(120,120,190)"), // Periwinkle + colord("rgb(150,110,190)"), // Lavender + colord("rgb(160,120,160)"), // Purple Gray + colord("rgb(170,140,190)"), // Medium Purple + colord("rgb(180,130,180)"), // Plum + colord("rgb(190,140,150)"), // Puce + colord("rgb(180,100,230)"), // Purple + colord("rgb(180,160,180)"), // Mauve + colord("rgb(170,150,170)"), // Dusty Rose + colord("rgb(150,130,150)"), // Thistle + colord("rgb(230,180,180)"), // Light Pink + colord("rgb(210,160,200)"), // Orchid + colord("rgb(230,130,180)"), // Pink + colord("rgb(210,100,160)"), // Hot Pink + colord("rgb(190,100,130)"), // Maroon + colord("rgb(220,120,120)"), // Coral + colord("rgb(200,130,110)"), // Dark Salmon + colord("rgb(230,140,140)"), // Salmon colord("rgb(230,100,100)"), // Bright Red - colord("rgb(100,180,230)"), // Sky Blue - colord("rgb(230,180,80)"), // Golden Yellow - colord("rgb(180,100,230)"), // Purple - colord("rgb(80,200,120)"), // Emerald Green - colord("rgb(230,130,180)"), // Pink - colord("rgb(100,160,80)"), // Olive Green colord("rgb(230,150,100)"), // Peach - colord("rgb(80,130,190)"), // Navy Blue - colord("rgb(210,210,100)"), // Lime Yellow - colord("rgb(190,100,130)"), // Maroon - colord("rgb(100,210,210)"), // Turquoise colord("rgb(210,140,80)"), // Light Orange - colord("rgb(150,110,190)"), // Lavender - colord("rgb(180,210,120)"), // Light Green - colord("rgb(210,100,160)"), // Hot Pink - colord("rgb(100,140,110)"), // Sea Green - colord("rgb(230,180,180)"), // Light Pink - colord("rgb(120,120,190)"), // Periwinkle - colord("rgb(190,170,100)"), // Sand - colord("rgb(100,180,160)"), // Aquamarine - colord("rgb(210,160,200)"), // Orchid - colord("rgb(170,190,100)"), // Yellow Green - colord("rgb(100,130,150)"), // Steel Blue - colord("rgb(230,140,140)"), // Salmon - colord("rgb(140,180,220)"), // Light Blue - colord("rgb(200,160,110)"), // Tan - colord("rgb(180,130,180)"), // Plum - colord("rgb(130,200,130)"), // Light Sea Green - colord("rgb(220,120,120)"), // Coral - colord("rgb(120,160,200)"), // Cornflower Blue - colord("rgb(200,200,140)"), // Khaki - colord("rgb(160,120,160)"), // Purple Gray - colord("rgb(140,180,140)"), // Dark Sea Green - colord("rgb(200,130,110)"), // Dark Salmon - colord("rgb(130,170,190)"), // Cadet Blue - colord("rgb(190,180,160)"), // Tan Gray - colord("rgb(170,140,190)"), // Medium Purple - colord("rgb(160,190,160)"), // Pale Green - colord("rgb(190,150,130)"), // Rosy Brown - colord("rgb(140,150,180)"), // Light Slate Gray - colord("rgb(180,170,140)"), // Dark Khaki - colord("rgb(150,130,150)"), // Thistle - colord("rgb(170,190,180)"), // Pale Blue Green - colord("rgb(190,140,150)"), // Puce - colord("rgb(130,180,170)"), // Medium Aquamarine - colord("rgb(180,160,180)"), // Mauve - colord("rgb(160,180,140)"), // Dark Olive Green - colord("rgb(170,150,170)"), // Dusty Rose - colord("rgb(100,180,230)"), // Sky Blue colord("rgb(230,180,80)"), // Golden Yellow - colord("rgb(180,100,230)"), // Purple - colord("rgb(80,200,120)"), // Emerald Green - colord("rgb(230,130,180)"), // Pink - colord("rgb(100,160,80)"), // Olive Green - colord("rgb(230,150,100)"), // Peach - colord("rgb(80,130,190)"), // Navy Blue - colord("rgb(210,210,100)"), // Lime Yellow - colord("rgb(190,100,130)"), // Maroon - colord("rgb(100,210,210)"), // Turquoise - colord("rgb(210,140,80)"), // Light Orange - colord("rgb(150,110,190)"), // Lavender - colord("rgb(180,210,120)"), // Light Green - colord("rgb(210,100,160)"), // Hot Pink - colord("rgb(100,140,110)"), // Sea Green - colord("rgb(230,180,180)"), // Light Pink - colord("rgb(120,120,190)"), // Periwinkle - colord("rgb(190,170,100)"), // Sand - colord("rgb(100,180,160)"), // Aquamarine - colord("rgb(210,160,200)"), // Orchid - colord("rgb(170,190,100)"), // Yellow Green - colord("rgb(100,130,150)"), // Steel Blue - colord("rgb(230,140,140)"), // Salmon - colord("rgb(140,180,220)"), // Light Blue colord("rgb(200,160,110)"), // Tan - colord("rgb(180,130,180)"), // Plum - colord("rgb(130,200,130)"), // Light Sea Green - colord("rgb(220,120,120)"), // Coral - colord("rgb(120,160,200)"), // Cornflower Blue - colord("rgb(200,200,140)"), // Khaki - colord("rgb(160,120,160)"), // Purple Gray - colord("rgb(140,180,140)"), // Dark Sea Green - colord("rgb(200,130,110)"), // Dark Salmon - colord("rgb(130,170,190)"), // Cadet Blue - colord("rgb(190,180,160)"), // Tan Gray - colord("rgb(170,140,190)"), // Medium Purple - colord("rgb(160,190,160)"), // Pale Green colord("rgb(190,150,130)"), // Rosy Brown - colord("rgb(140,150,180)"), // Light Slate Gray + colord("rgb(190,180,160)"), // Tan Gray colord("rgb(180,170,140)"), // Dark Khaki - colord("rgb(150,130,150)"), // Thistle - colord("rgb(170,190,180)"), // Pale Blue Green - colord("rgb(190,140,150)"), // Puce - colord("rgb(130,180,170)"), // Medium Aquamarine - colord("rgb(180,160,180)"), // Mauve - colord("rgb(160,180,140)"), // Dark Olive Green - colord("rgb(170,150,170)"), // Dusty Rose + colord("rgb(200,200,140)"), // Khaki + colord("rgb(190,170,100)"), // Sand ]; // Bright pastel theme with 64 colors export const humanColors: Colord[] = [ - colord("rgb(16,185,129)"), // Sea Green - colord("rgb(34,197,94)"), // Emerald - colord("rgb(45,212,191)"), // Turquoise - colord("rgb(48,178,180)"), // Teal - colord("rgb(52,211,153)"), // Spearmint - colord("rgb(56,189,248)"), // Light Blue - colord("rgb(59,130,246)"), // Royal Blue - colord("rgb(67,190,84)"), // Fresh Green - colord("rgb(74,222,128)"), // Mint - colord("rgb(79,70,229)"), // Indigo - colord("rgb(82,183,136)"), // Jade - colord("rgb(96,165,250)"), // Sky Blue - colord("rgb(99,202,253)"), // Azure - colord("rgb(110,231,183)"), // Seafoam - colord("rgb(124,58,237)"), // Royal Purple - colord("rgb(125,211,252)"), // Crystal Blue - colord("rgb(132,204,22)"), // Lime - colord("rgb(133,77,14)"), // Chocolate - colord("rgb(134,239,172)"), // Light Green - colord("rgb(147,51,234)"), // Bright Purple - colord("rgb(147,197,253)"), // Powder Blue - colord("rgb(151,255,187)"), // Fresh Mint colord("rgb(163,230,53)"), // Yellow Green - colord("rgb(167,139,250)"), // Periwinkle - colord("rgb(168,85,247)"), // Vibrant Purple - colord("rgb(179,136,255)"), // Light Purple + colord("rgb(132,204,22)"), // Lime + colord("rgb(16,185,129)"), // Sea Green + colord("rgb(52,211,153)"), // Spearmint + colord("rgb(45,212,191)"), // Turquoise + colord("rgb(74,222,128)"), // Mint + colord("rgb(110,231,183)"), // Seafoam + colord("rgb(134,239,172)"), // Light Green + colord("rgb(151,255,187)"), // Fresh Mint colord("rgb(186,255,201)"), // Pale Emerald + colord("rgb(230,250,210)"), // Pastel Lime + colord("rgb(34,197,94)"), // Emerald + colord("rgb(67,190,84)"), // Fresh Green + colord("rgb(82,183,136)"), // Jade + colord("rgb(48,178,180)"), // Teal + colord("rgb(230,255,250)"), // Mint Whisper + colord("rgb(220,240,250)"), // Ice Blue + colord("rgb(233,213,255)"), // Light Lilac + colord("rgb(204,204,255)"), // Soft Lavender Blue + colord("rgb(220,220,255)"), // Meringue Blue + colord("rgb(202,225,255)"), // Baby Blue + colord("rgb(147,197,253)"), // Powder Blue + colord("rgb(125,211,252)"), // Crystal Blue + colord("rgb(99,202,253)"), // Azure + colord("rgb(56,189,248)"), // Light Blue + colord("rgb(96,165,250)"), // Sky Blue + colord("rgb(59,130,246)"), // Royal Blue + colord("rgb(79,70,229)"), // Indigo + colord("rgb(124,58,237)"), // Royal Purple + colord("rgb(147,51,234)"), // Bright Purple + colord("rgb(179,136,255)"), // Light Purple + colord("rgb(167,139,250)"), // Periwinkle + colord("rgb(217,70,239)"), // Fuchsia + colord("rgb(168,85,247)"), // Vibrant Purple colord("rgb(190,92,251)"), // Amethyst colord("rgb(192,132,252)"), // Lavender - colord("rgb(202,138,4)"), // Rich Gold - colord("rgb(202,225,255)"), // Baby Blue - colord("rgb(204,204,255)"), // Soft Lavender Blue - colord("rgb(217,70,239)"), // Fuchsia - colord("rgb(220,38,38)"), // Ruby - colord("rgb(220,220,255)"), // Meringue Blue - colord("rgb(220,240,250)"), // Ice Blue - colord("rgb(230,250,210)"), // Pastel Lime - colord("rgb(230,255,250)"), // Mint Whisper - colord("rgb(233,213,255)"), // Light Lilac - colord("rgb(234,88,12)"), // Burnt Orange - colord("rgb(234,179,8)"), // Sunflower - colord("rgb(235,75,75)"), // Bright Red - colord("rgb(236,72,153)"), // Deep Pink - colord("rgb(239,68,68)"), // Crimson colord("rgb(240,171,252)"), // Orchid - colord("rgb(240,240,200)"), // Light Khaki colord("rgb(244,114,182)"), // Rose + colord("rgb(236,72,153)"), // Deep Pink + colord("rgb(220,38,38)"), // Ruby + colord("rgb(239,68,68)"), // Crimson + colord("rgb(235,75,75)"), // Bright Red colord("rgb(245,101,101)"), // Coral - colord("rgb(245,158,11)"), // Amber colord("rgb(248,113,113)"), // Warm Red - colord("rgb(249,115,22)"), // Tangerine - colord("rgb(250,215,225)"), // Cotton Candy - colord("rgb(250,250,210)"), // Pastel Lemon colord("rgb(251,113,133)"), // Watermelon - colord("rgb(251,146,60)"), // Light Orange - colord("rgb(251,191,36)"), // Marigold - colord("rgb(251,235,245)"), // Rose Powder - colord("rgb(252,165,165)"), // Peach - colord("rgb(252,211,77)"), // Golden colord("rgb(253,164,175)"), // Salmon Pink + colord("rgb(252,165,165)"), // Peach colord("rgb(255,204,229)"), // Blush Pink - colord("rgb(255,223,186)"), // Apricot Cream + colord("rgb(250,215,225)"), // Cotton Candy + colord("rgb(251,235,245)"), // Rose Powder + colord("rgb(240,240,200)"), // Light Khaki + colord("rgb(250,250,210)"), // Pastel Lemon colord("rgb(255,240,200)"), // Vanilla + colord("rgb(255,223,186)"), // Apricot Cream + colord("rgb(252,211,77)"), // Golden + colord("rgb(251,191,36)"), // Marigold + colord("rgb(234,179,8)"), // Sunflower + colord("rgb(202,138,4)"), // Rich Gold + colord("rgb(245,158,11)"), // Amber + colord("rgb(251,146,60)"), // Light Orange + colord("rgb(249,115,22)"), // Tangerine + colord("rgb(234,88,12)"), // Burnt Orange + colord("rgb(133,77,14)"), // Chocolate ]; export const botColors: Colord[] = [ - colord("rgb(190,120,120)"), // Muted Red - colord("rgb(120,160,190)"), // Muted Sky Blue - colord("rgb(190,160,100)"), // Muted Golden Yellow - colord("rgb(160,120,190)"), // Muted Purple - colord("rgb(100,170,130)"), // Muted Emerald Green - colord("rgb(190,130,160)"), // Muted Pink - colord("rgb(120,150,100)"), // Muted Olive Green - colord("rgb(190,140,120)"), // Muted Peach - colord("rgb(100,120,160)"), // Muted Navy Blue - colord("rgb(170,170,120)"), // Muted Lime Yellow - colord("rgb(160,120,130)"), // Muted Maroon - colord("rgb(120,170,170)"), // Muted Turquoise - colord("rgb(170,140,100)"), // Muted Light Orange - colord("rgb(140,120,160)"), // Muted Lavender - colord("rgb(150,170,130)"), // Muted Light Green - colord("rgb(170,120,140)"), // Muted Hot Pink - colord("rgb(120,140,120)"), // Muted Sea Green - colord("rgb(180,160,160)"), // Muted Light Pink - colord("rgb(130,130,160)"), // Muted Periwinkle - colord("rgb(160,150,120)"), // Muted Sand - colord("rgb(120,160,150)"), // Muted Aquamarine - colord("rgb(170,150,170)"), // Muted Orchid - colord("rgb(150,160,120)"), // Muted Yellow Green - colord("rgb(120,130,140)"), // Muted Steel Blue - colord("rgb(180,140,140)"), // Muted Salmon - colord("rgb(140,160,170)"), // Muted Light Blue - colord("rgb(170,150,130)"), // Muted Tan - colord("rgb(160,130,160)"), // Muted Plum - colord("rgb(130,170,130)"), // Muted Light Sea Green - colord("rgb(170,130,130)"), // Muted Coral - colord("rgb(130,150,170)"), // Muted Cornflower Blue - colord("rgb(170,170,140)"), // Muted Khaki - colord("rgb(150,130,150)"), // Muted Purple Gray - colord("rgb(140,160,140)"), // Muted Dark Sea Green - colord("rgb(170,130,120)"), // Muted Dark Salmon - colord("rgb(130,150,160)"), // Muted Cadet Blue - colord("rgb(160,160,150)"), // Muted Tan Gray - colord("rgb(150,140,160)"), // Muted Medium Purple - colord("rgb(150,170,150)"), // Muted Pale Green - colord("rgb(160,140,130)"), // Muted Rosy Brown - colord("rgb(140,150,160)"), // Muted Light Slate Gray - colord("rgb(160,150,140)"), // Muted Dark Khaki - colord("rgb(140,130,140)"), // Muted Thistle - colord("rgb(150,160,160)"), // Muted Pale Blue Green - colord("rgb(160,140,150)"), // Muted Puce - colord("rgb(130,160,150)"), // Muted Medium Aquamarine - colord("rgb(160,150,160)"), // Muted Mauve colord("rgb(150,160,140)"), // Muted Dark Olive Green + colord("rgb(160,160,150)"), // Muted Tan Gray + colord("rgb(170,170,140)"), // Muted Khaki + colord("rgb(170,170,120)"), // Muted Lime Yellow + colord("rgb(150,160,120)"), // Muted Yellow Green + colord("rgb(150,170,130)"), // Muted Light Green + colord("rgb(150,170,150)"), // Muted Pale Green + colord("rgb(130,170,130)"), // Muted Light Sea Green + colord("rgb(140,160,140)"), // Muted Dark Sea Green + colord("rgb(120,150,100)"), // Muted Olive Green + colord("rgb(120,140,120)"), // Muted Sea Green + colord("rgb(100,170,130)"), // Muted Emerald Green + colord("rgb(120,160,150)"), // Muted Aquamarine + colord("rgb(130,160,150)"), // Muted Medium Aquamarine + colord("rgb(120,170,170)"), // Muted Turquoise + colord("rgb(120,160,190)"), // Muted Sky Blue + colord("rgb(130,150,170)"), // Muted Cornflower Blue + colord("rgb(130,150,160)"), // Muted Cadet Blue + colord("rgb(140,150,160)"), // Muted Light Slate Gray + colord("rgb(140,160,170)"), // Muted Light Blue + colord("rgb(150,160,160)"), // Muted Pale Blue Green + colord("rgb(100,120,160)"), // Muted Navy Blue + colord("rgb(120,130,140)"), // Muted Steel Blue + colord("rgb(130,130,160)"), // Muted Periwinkle + colord("rgb(140,130,140)"), // Muted Thistle + colord("rgb(140,120,160)"), // Muted Lavender + colord("rgb(150,130,150)"), // Muted Purple Gray + colord("rgb(150,140,160)"), // Muted Medium Purple + colord("rgb(160,130,160)"), // Muted Plum + colord("rgb(170,150,170)"), // Muted Orchid + colord("rgb(160,120,190)"), // Muted Purple + colord("rgb(160,120,130)"), // Muted Maroon + colord("rgb(170,120,140)"), // Muted Hot Pink + colord("rgb(170,130,120)"), // Muted Dark Salmon + colord("rgb(170,130,130)"), // Muted Coral + colord("rgb(180,140,140)"), // Muted Salmon + colord("rgb(190,130,160)"), // Muted Pink + colord("rgb(190,120,120)"), // Muted Red + colord("rgb(190,140,120)"), // Muted Peach + colord("rgb(190,160,100)"), // Muted Golden Yellow + colord("rgb(170,140,100)"), // Muted Light Orange + colord("rgb(160,140,130)"), // Muted Rosy Brown + colord("rgb(170,150,130)"), // Muted Tan + colord("rgb(160,150,120)"), // Muted Sand + colord("rgb(160,150,140)"), // Muted Dark Khaki + colord("rgb(160,140,150)"), // Muted Puce + colord("rgb(160,150,160)"), // Muted Mauve colord("rgb(150,140,150)"), // Muted Dusty Rose + colord("rgb(180,160,160)"), // Muted Light Pink ]; // Fallback colors for when the color palette is exhausted. diff --git a/src/core/configuration/Config.ts b/src/core/configuration/Config.ts index 696bc8d26..f1f1b03c6 100644 --- a/src/core/configuration/Config.ts +++ b/src/core/configuration/Config.ts @@ -190,6 +190,8 @@ export interface Theme { // Don't call directly, use PlayerView territoryColor(playerInfo: PlayerView): Colord; // Don't call directly, use PlayerView + structureColors(territoryColor: Colord): { light: Colord; dark: Colord }; + // Don't call directly, use PlayerView borderColor(territoryColor: Colord): Colord; // Don't call directly, use PlayerView defendedBorderColors(territoryColor: Colord): { light: Colord; dark: Colord }; diff --git a/src/core/configuration/PastelTheme.ts b/src/core/configuration/PastelTheme.ts index 028fec8bf..b798423fa 100644 --- a/src/core/configuration/PastelTheme.ts +++ b/src/core/configuration/PastelTheme.ts @@ -1,4 +1,4 @@ -import { Colord, colord } from "colord"; +import { Colord, colord, LabaColor } from "colord"; import { PseudoRandom } from "../PseudoRandom"; import { PlayerType, Team, TerrainType } from "../game/Game"; import { GameMap, TileRef } from "../game/GameMap"; @@ -65,6 +65,59 @@ export class PastelTheme implements Theme { return this.nationColorAllocator.assignColor(player.id()); } + structureColors(territoryColor: Colord): { light: Colord; dark: Colord } { + // Convert territory color to LAB color space. Territory color is rendered in game with alpha = 150/255, use that here. + const lightLAB = territoryColor.alpha(150 / 255).toLab(); + // Get "border color" from territory color & convert to LAB color space + const darkLAB = this.borderColor(territoryColor).toLab(); + // Calculate the contrast of the two provided colors + let contrast = this.contrast(lightLAB, darkLAB); + + // Don't want excessive contrast, so incrementally increase contrast within a loop. + // Define target values, looping limits, and loop counter + const loopLimit = 10; // Switch from darkening border to lightening fill if loopLimit is reached + const maxIterations = 50; // maximum number of loops allowed, throw error above this limit + const contrastTarget = 0.5; + let loopCount = 0; + + // Adjust luminance by 5 in each iteration. This is a balance between speed and not overdoing contrast changes. + const luminanceChange = 5; + + while (contrast < contrastTarget) { + if (loopCount > maxIterations) { + // Prevent runaway loops + console.warn(`Infinite loop detected during structure color calculation. + Light color: ${colord(lightLAB).toRgbString()}, + Dark color: ${colord(darkLAB).toRgbString()}, + Contrast: ${contrast}`); + break; + + // Increase the light color if the "loop limit" has been reach + // (probably due to the dark color already being as dark as it can be) + } else if (loopCount > loopLimit) { + lightLAB.l = this.clamp(lightLAB.l + luminanceChange); + + // Decrease the dark color first to keep the light color as close + // to the territory color as possible + } else { + darkLAB.l = this.clamp(darkLAB.l - luminanceChange); + } + + // re-calculate contrast and increment loop counter + contrast = this.contrast(lightLAB, darkLAB); + loopCount++; + } + return { light: colord(lightLAB), dark: colord(darkLAB) }; + } + + private contrast(first: LabaColor, second: LabaColor): number { + return colord(first).delta(colord(second)); + } + + private clamp(num: number, low: number = 0, high: number = 100): number { + return Math.min(Math.max(low, num), high); + } + // Don't call directly, use PlayerView borderColor(territoryColor: Colord): Colord { return territoryColor.darken(0.125); diff --git a/src/core/game/GameView.ts b/src/core/game/GameView.ts index ccceacef9..471555751 100644 --- a/src/core/game/GameView.ts +++ b/src/core/game/GameView.ts @@ -184,6 +184,8 @@ export class PlayerView { private _territoryColor: Colord; private _borderColor: Colord; + // Update here to include structure light and dark colors + private _structureColors: { light: Colord; dark: Colord }; private _defendedBorderColors: { light: Colord; dark: Colord }; constructor( @@ -229,6 +231,11 @@ export class PlayerView { this._territoryColor = defaultTerritoryColor; } + this._structureColors = this.game + .config() + .theme() + .structureColors(this._territoryColor); + const maybeFocusedBorderColor = this.game.myClientID() === this.data.clientID ? this.game.config().theme().focusedBorderColor() @@ -262,6 +269,10 @@ export class PlayerView { return isPrimary ? this._territoryColor : this._borderColor; } + structureColors(): { light: Colord; dark: Colord } { + return this._structureColors; + } + borderColor(tile?: TileRef, isDefended: boolean = false): Colord { if (tile === undefined || !isDefended) { return this._borderColor;