Replace battle maps 47 and 48 with hand-painted assets
@@ -2,7 +2,7 @@
|
||||
|
||||
## Scope
|
||||
|
||||
The first forty-six campaign battles now use the same hand-painted tactical map pipeline. The renderer still reads the original scenario tile coordinates and battle logic; only the map texture asset changes from flat/vector map art to low-contrast raster terrain.
|
||||
The first forty-eight campaign battles now use the same hand-painted tactical map pipeline. The renderer still reads the original scenario tile coordinates and battle logic; only the map texture asset changes from flat/vector map art to low-contrast raster terrain.
|
||||
|
||||
## Art Direction
|
||||
|
||||
@@ -72,6 +72,8 @@ python scripts/generate-handpaint-map-sample.py --map forty-third --webp-quality
|
||||
python scripts/generate-handpaint-map-sample.py --map forty-fourth --webp-quality 90
|
||||
python scripts/generate-handpaint-map-sample.py --map forty-fifth --webp-quality 90
|
||||
python scripts/generate-handpaint-map-sample.py --map forty-sixth --webp-quality 90
|
||||
python scripts/generate-handpaint-map-sample.py --map forty-seventh --webp-quality 90
|
||||
python scripts/generate-handpaint-map-sample.py --map forty-eighth --webp-quality 90
|
||||
```
|
||||
|
||||
Comparison example:
|
||||
@@ -128,6 +130,8 @@ python scripts/generate-handpaint-map-sample.py --map thirtieth --tile-size 192
|
||||
- `src/assets/images/battle/forty-fourth-battle-map.webp`
|
||||
- `src/assets/images/battle/forty-fifth-battle-map.webp`
|
||||
- `src/assets/images/battle/forty-sixth-battle-map.webp`
|
||||
- `src/assets/images/battle/forty-seventh-battle-map.webp`
|
||||
- `src/assets/images/battle/forty-eighth-battle-map.webp`
|
||||
|
||||
## QA Outputs
|
||||
|
||||
@@ -221,5 +225,9 @@ python scripts/generate-handpaint-map-sample.py --map thirtieth --tile-size 192
|
||||
- `docs/forty-fifth-battle-map-handpaint-preview.png`
|
||||
- `docs/forty-sixth-battle-map-handpaint-before-after.png`
|
||||
- `docs/forty-sixth-battle-map-handpaint-preview.png`
|
||||
- `docs/forty-seventh-battle-map-handpaint-before-after.png`
|
||||
- `docs/forty-seventh-battle-map-handpaint-preview.png`
|
||||
- `docs/forty-eighth-battle-map-handpaint-before-after.png`
|
||||
- `docs/forty-eighth-battle-map-handpaint-preview.png`
|
||||
|
||||
Browser screenshots are saved per verification run after build/deploy.
|
||||
|
||||
BIN
docs/forty-eighth-battle-map-handpaint-before-after.png
Normal file
|
After Width: | Height: | Size: 2.6 MiB |
BIN
docs/forty-eighth-battle-map-handpaint-preview.png
Normal file
|
After Width: | Height: | Size: 2.3 MiB |
BIN
docs/forty-seventh-battle-map-handpaint-before-after.png
Normal file
|
After Width: | Height: | Size: 2.8 MiB |
BIN
docs/forty-seventh-battle-map-handpaint-preview.png
Normal file
|
After Width: | Height: | Size: 2.3 MiB |
@@ -458,6 +458,26 @@ MAP_CONFIGS = {
|
||||
"seed": 241154,
|
||||
"tile_size": ULTRA_LARGE_MAP_TILE_SIZE,
|
||||
},
|
||||
"forty-seventh": {
|
||||
"slug": "forty-seventh-battle-map",
|
||||
"terrain_export": "fortySeventhBattleMap",
|
||||
"units_export": "fortySeventhBattleUnits",
|
||||
"ally_positions_export": "fortySeventhBattleAllyPositions",
|
||||
"out": BATTLE_IMAGE_DIR / "forty-seventh-battle-map.webp",
|
||||
"before": BATTLE_IMAGE_DIR / "forty-seventh-battle-map.svg",
|
||||
"seed": 241164,
|
||||
"tile_size": ULTRA_LARGE_MAP_TILE_SIZE,
|
||||
},
|
||||
"forty-eighth": {
|
||||
"slug": "forty-eighth-battle-map",
|
||||
"terrain_export": "fortyEighthBattleMap",
|
||||
"units_export": "fortyEighthBattleUnits",
|
||||
"ally_positions_export": "fortyEighthBattleAllyPositions",
|
||||
"out": BATTLE_IMAGE_DIR / "forty-eighth-battle-map.webp",
|
||||
"before": BATTLE_IMAGE_DIR / "forty-eighth-battle-map.svg",
|
||||
"seed": 241174,
|
||||
"tile_size": ULTRA_LARGE_MAP_TILE_SIZE,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 9600 7800" width="9600" height="7800">
|
||||
<defs>
|
||||
<linearGradient id="ground" x1="0" y1="0" x2="1" y2="1">
|
||||
<stop offset="0" stop-color="#927d48"/>
|
||||
<stop offset="0.46" stop-color="#695d37"/>
|
||||
<stop offset="1" stop-color="#3c4026"/>
|
||||
</linearGradient>
|
||||
<pattern id="grass" width="180" height="180" patternUnits="userSpaceOnUse">
|
||||
<rect width="180" height="180" fill="#586c35"/>
|
||||
<path d="M18 118l22-42 24 38m34-8 26-56 30 54m-16 50 28-34 28 38" stroke="#8fb354" stroke-width="13" fill="none" stroke-linecap="round"/>
|
||||
<path d="M6 42c48 18 75 17 121-6M28 160c42-18 84-20 131 0" stroke="#2f3b22" stroke-width="8" fill="none" opacity=".65"/>
|
||||
</pattern>
|
||||
<pattern id="stone" width="220" height="220" patternUnits="userSpaceOnUse">
|
||||
<rect width="220" height="220" fill="#4a4a31"/>
|
||||
<path d="M0 64c46-42 96-48 150-12 34 22 55 24 70 16M26 154c60-38 122-38 184 0M88 0c-18 46-10 86 26 120" stroke="#222516" stroke-width="15" fill="none" opacity=".8"/>
|
||||
<path d="M24 76c45 14 82 9 112-14M66 174c40 13 74 8 102-14" stroke="#8a8657" stroke-width="10" fill="none" opacity=".55"/>
|
||||
</pattern>
|
||||
<pattern id="road" width="210" height="210" patternUnits="userSpaceOnUse">
|
||||
<rect width="210" height="210" fill="#947a46"/>
|
||||
<path d="M0 70c60-28 118-30 210-5M0 150c66-28 133-29 210 2" stroke="#b69a5e" stroke-width="16" fill="none" opacity=".72"/>
|
||||
<path d="M24 22h34M88 110h46M154 184h34" stroke="#5f4a2f" stroke-width="12" stroke-linecap="round" opacity=".65"/>
|
||||
</pattern>
|
||||
<pattern id="village" width="260" height="260" patternUnits="userSpaceOnUse">
|
||||
<rect width="260" height="260" fill="#74623e"/>
|
||||
<path d="M36 154h78v62H36zM146 124h74v92h-74z" fill="#4e3c27"/>
|
||||
<path d="M22 154l54-62 54 62M132 124l50-66 54 66" fill="#c78329"/>
|
||||
<path d="M52 172h22v44M162 144h28v72" stroke="#d9b866" stroke-width="10"/>
|
||||
</pattern>
|
||||
<pattern id="camp" width="280" height="280" patternUnits="userSpaceOnUse">
|
||||
<rect width="280" height="280" fill="#594f31"/>
|
||||
<path d="M44 214 96 76l54 138zM144 214l58-156 52 156z" fill="#b46c22" stroke="#2a2218" stroke-width="10"/>
|
||||
<path d="M96 76v138M202 58v156" stroke="#ead6a2" stroke-width="9"/>
|
||||
<path d="M26 232h226" stroke="#2b2419" stroke-width="14" stroke-linecap="round"/>
|
||||
</pattern>
|
||||
<filter id="softShadow" x="-20%" y="-20%" width="140%" height="140%">
|
||||
<feDropShadow dx="0" dy="24" stdDeviation="20" flood-color="#10140d" flood-opacity=".45"/>
|
||||
</filter>
|
||||
</defs>
|
||||
<rect width="9600" height="7800" fill="url(#ground)"/>
|
||||
<rect x="120" y="0" width="3000" height="3600" fill="url(#stone)" opacity=".78"/>
|
||||
<rect x="3540" y="0" width="2760" height="2600" fill="url(#stone)" opacity=".7"/>
|
||||
<rect x="6720" y="0" width="2760" height="3220" fill="url(#stone)" opacity=".73"/>
|
||||
<rect x="8520" y="2920" width="960" height="1900" fill="url(#stone)" opacity=".72"/>
|
||||
<rect x="2420" y="2050" width="4360" height="4650" fill="url(#grass)" opacity=".82"/>
|
||||
<rect x="5000" y="2740" width="3860" height="4300" fill="url(#grass)" opacity=".84"/>
|
||||
<rect x="160" y="4640" width="3260" height="2200" fill="url(#grass)" opacity=".74"/>
|
||||
<rect x="7420" y="3820" width="2080" height="3000" fill="url(#grass)" opacity=".78"/>
|
||||
<path d="M220 5560C1740 5460 3620 5600 5110 5640s2870 30 4240 160" stroke="#9e7e3f" stroke-width="520" fill="none" opacity=".95"/>
|
||||
<path d="M2280 6440c1350-80 2840-20 4150 140 1010 124 1810 154 2680-80" stroke="#9f8249" stroke-width="420" fill="none" opacity=".95"/>
|
||||
<path d="M3320 6280c-30-840 110-1650 310-2440" stroke="#95783e" stroke-width="460" fill="none" opacity=".92"/>
|
||||
<path d="M6600 6380c40-1380 70-2750 100-3970" stroke="#987d44" stroke-width="500" fill="none" opacity=".92"/>
|
||||
<path d="M7160 3820c640-140 1320-125 1960 80" stroke="#9f8249" stroke-width="430" fill="none" opacity=".95"/>
|
||||
<path d="M0 7050c1100 140 2440 80 3820 70 510-4 610 460 620 680H0z" fill="#244d63" opacity=".85"/>
|
||||
<path d="M4300 5480c340 700 710 1470 1160 2320h-1120c-330-660-560-1370-620-2170z" fill="#2d6574" opacity=".82"/>
|
||||
<path d="M0 6140c760-70 1440-20 1980 180 280 520 320 1010 90 1480H0z" fill="#2e6579" opacity=".78"/>
|
||||
<path d="M7400 5040c420 520 640 1160 700 2040l-840-20c-120-750-260-1320-450-1730z" fill="#2b5d72" opacity=".76"/>
|
||||
<g filter="url(#softShadow)">
|
||||
<rect x="1040" y="4860" width="1500" height="1260" fill="url(#village)" opacity=".88"/>
|
||||
<rect x="4680" y="4140" width="1240" height="1440" fill="url(#village)" opacity=".88"/>
|
||||
<rect x="7260" y="4340" width="1600" height="1200" fill="url(#village)" opacity=".88"/>
|
||||
<rect x="1740" y="3840" width="1100" height="940" fill="url(#stone)" opacity=".86"/>
|
||||
<rect x="7720" y="3140" width="1440" height="1240" fill="url(#stone)" opacity=".9"/>
|
||||
<rect x="5480" y="5480" width="1220" height="1080" fill="url(#camp)" opacity=".9"/>
|
||||
<rect x="3180" y="4440" width="1260" height="1080" fill="url(#camp)" opacity=".9"/>
|
||||
</g>
|
||||
<g opacity=".38">
|
||||
<path d="M380 3520c1080 220 1770 150 2670-180M3740 2600c910 160 1650 120 2420-180M6800 3240c820 220 1570 200 2410-40" stroke="#d0b76f" stroke-width="60" fill="none"/>
|
||||
<path d="M260 6880c1180 280 2320 280 3460 20M5160 7000c1240 230 2380 210 3500-80" stroke="#8cc0c0" stroke-width="54" fill="none"/>
|
||||
</g>
|
||||
<rect x="0" y="0" width="9600" height="7800" fill="none" stroke="#1d1b12" stroke-width="60"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 5.4 KiB |
BIN
src/assets/images/battle/forty-eighth-battle-map.webp
Normal file
|
After Width: | Height: | Size: 16 MiB |
@@ -1,81 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="9400" height="7600" viewBox="0 0 9400 7600">
|
||||
<defs>
|
||||
<linearGradient id="ground" x1="0" x2="1" y1="0" y2="1">
|
||||
<stop offset="0" stop-color="#8d8a52"/>
|
||||
<stop offset=".42" stop-color="#5f773f"/>
|
||||
<stop offset=".74" stop-color="#3f6035"/>
|
||||
<stop offset="1" stop-color="#2f4a31"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="river" x1="0" x2="1" y1="0" y2="0">
|
||||
<stop offset="0" stop-color="#2c6a73"/>
|
||||
<stop offset=".5" stop-color="#23506b"/>
|
||||
<stop offset="1" stop-color="#2c6f76"/>
|
||||
</linearGradient>
|
||||
<pattern id="grain" width="94" height="94" patternUnits="userSpaceOnUse">
|
||||
<path d="M0 46h94M46 0v94" stroke="#152112" stroke-width="5" opacity=".06"/>
|
||||
<circle cx="20" cy="20" r="8" fill="#cbb369" opacity=".13"/>
|
||||
<circle cx="62" cy="60" r="7" fill="#1c321c" opacity=".18"/>
|
||||
<path d="M7 80c22-15 46-14 73 2" stroke="#385929" stroke-width="5" opacity=".15" fill="none"/>
|
||||
</pattern>
|
||||
<filter id="softShadow" x="-18%" y="-18%" width="136%" height="136%">
|
||||
<feDropShadow dx="0" dy="25" stdDeviation="22" flood-color="#0f160c" flood-opacity=".38"/>
|
||||
</filter>
|
||||
</defs>
|
||||
<rect width="9400" height="7600" fill="url(#ground)"/>
|
||||
<rect width="9400" height="7600" fill="url(#grain)"/>
|
||||
|
||||
<g opacity=".92">
|
||||
<path d="M0 6680c980-250 1710-80 2680-95 850-12 1530-290 2350-180 870 115 1730 420 2530 250 650-140 1150-240 1840-60v1005H0z" fill="url(#river)"/>
|
||||
<path d="M960 6040c300 640 510 1050 760 1560H520c-210-430-330-930-410-1510z" fill="#2d6470"/>
|
||||
<path d="M4600 5480c310 820 400 1400 220 2120h-520c130-730 10-1360-220-2000z" fill="#23566b" opacity=".88"/>
|
||||
<path d="M360 6650c620 180 1160 210 1800 95M4580 6230c710 160 1230 310 1990 430M6840 6710c760 100 1390 45 2240-90" stroke="#91c4ae" stroke-width="26" opacity=".23" fill="none"/>
|
||||
</g>
|
||||
|
||||
<g filter="url(#softShadow)">
|
||||
<path d="M0 0h2900c-160 700-540 1340-1080 1800-640 545-1150 1050-1820 1480z" fill="#4b562f"/>
|
||||
<path d="M3450 0h2900c-150 570-490 990-970 1280-560 340-1210 500-2130 650z" fill="#505b31"/>
|
||||
<path d="M6600 0h2800v2950c-560-120-1040-410-1410-850-420-500-720-1150-1390-2100z" fill="#46542f"/>
|
||||
<path d="M9100 2680h300v3610c-340-230-520-620-570-1110-80-740 230-1480 270-2500z" fill="#3e4c2d"/>
|
||||
<path d="M3720 5700h520c55 690-65 1420-360 1900h-570c260-610 390-1240 410-1900z" fill="#44502e"/>
|
||||
</g>
|
||||
|
||||
<g opacity=".92">
|
||||
<path d="M140 4780c1280-260 2240-110 3360-130 1080-20 1850-285 2850-190 990 92 1840 280 2410 115" stroke="#b5965d" stroke-width="520" stroke-linecap="round" fill="none"/>
|
||||
<path d="M2030 5880c890-150 1890-70 2940 75 1240 170 2420 115 4020-230" stroke="#b08a55" stroke-width="420" stroke-linecap="round" fill="none"/>
|
||||
<path d="M3390 3360c160 840 105 1540-120 2180" stroke="#aa8351" stroke-width="300" stroke-linecap="round" fill="none"/>
|
||||
<path d="M6580 2460c-90 920 130 1670 430 2480" stroke="#aa8351" stroke-width="270" stroke-linecap="round" fill="none"/>
|
||||
</g>
|
||||
|
||||
<g opacity=".94">
|
||||
<path d="M2300 1800c730-310 1630-270 2440-60 650 170 1230 395 1920 390 560-5 1080-130 1680-390v880c-1100 380-2000 300-3040 20-820-220-1600-410-2540-80-560 195-1060 480-1520 865v-910c330-280 710-500 1060-715z" fill="#315f32"/>
|
||||
<path d="M3950 3260c960-260 1780-150 2440 170 850 410 1720 520 2800 135v1300c-760 260-1620 325-2470 70-820-250-1520-575-2500-315-610 160-1250 480-1950 890v-1400c500-400 1040-660 1680-850z" fill="#2f5b31"/>
|
||||
<path d="M290 4550c1030-280 1880-110 2660 220 650 275 1290 365 1940 220v980c-850 240-1670 75-2490-270-730-305-1460-375-2540-40z" fill="#386735"/>
|
||||
<circle cx="3300" cy="2480" r="185" fill="#1e351c" opacity=".55"/>
|
||||
<circle cx="5250" cy="4050" r="205" fill="#1e351c" opacity=".55"/>
|
||||
<circle cx="7760" cy="4550" r="170" fill="#1e351c" opacity=".55"/>
|
||||
<path d="M1100 4040c420-180 870-170 1290 10 420 175 860 220 1280 80v560c-500 175-990 125-1480-85-390-165-760-190-1090-60z" fill="#456d35" opacity=".86"/>
|
||||
</g>
|
||||
|
||||
<g filter="url(#softShadow)">
|
||||
<path d="M1180 4280h1220v1200H1180z" fill="#5d412b"/>
|
||||
<path d="M1300 4400h980v980h-980z" fill="#8b633c"/>
|
||||
<path d="M1390 4540h800M1390 4880h800M1390 5200h800" stroke="#dfbf75" stroke-width="34" opacity=".72"/>
|
||||
<path d="M4270 3880h1240v1160H4270z" fill="#58412b"/>
|
||||
<path d="M4400 4010h980v900h-980z" fill="#86653d"/>
|
||||
<path d="M4480 4160h820M4480 4510h820" stroke="#dfbf75" stroke-width="34" opacity=".72"/>
|
||||
<path d="M7160 3420h1380v1300H7160z" fill="#543c29"/>
|
||||
<path d="M7300 3560h1100v1020H7300z" fill="#83613c"/>
|
||||
<path d="M7420 3720h860M7420 4100h860" stroke="#dfbf75" stroke-width="36" opacity=".72"/>
|
||||
</g>
|
||||
|
||||
<g opacity=".8">
|
||||
<path d="M1580 4480l215-270 215 270-215 215zM1990 5100l190-230 190 230-190 190zM4470 4140l220-270 220 270-220 215zM5040 4600l190-230 190 230-190 190zM7440 3720l205-250 205 250-205 205zM8040 4230l180-220 180 220-180 180z" fill="#c99143"/>
|
||||
<path d="M620 5880c180-90 410-80 640 30M2920 5620c260-90 520-80 780 30M6420 5680c260-100 590-80 930 55" stroke="#27451f" stroke-width="52" stroke-linecap="round" opacity=".4"/>
|
||||
</g>
|
||||
|
||||
<g opacity=".55">
|
||||
<path d="M0 0h9400v7600H0z" fill="none" stroke="#17200f" stroke-width="36"/>
|
||||
<path d="M0 600h9400M0 1200h9400M0 1800h9400M0 2400h9400M0 3000h9400M0 3600h9400M0 4200h9400M0 4800h9400M0 5400h9400M0 6000h9400M0 6600h9400M0 7200h9400" stroke="#1f2c18" stroke-width="7" opacity=".25"/>
|
||||
<path d="M600 0v7600M1200 0v7600M1800 0v7600M2400 0v7600M3000 0v7600M3600 0v7600M4200 0v7600M4800 0v7600M5400 0v7600M6000 0v7600M6600 0v7600M7200 0v7600M7800 0v7600M8400 0v7600M9000 0v7600" stroke="#1f2c18" stroke-width="7" opacity=".25"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 5.6 KiB |
BIN
src/assets/images/battle/forty-seventh-battle-map.webp
Normal file
|
After Width: | Height: | Size: 16 MiB |
@@ -22,13 +22,13 @@ import fifthBattleMapUrl from '../../assets/images/battle/fifth-battle-map.webp'
|
||||
import fifteenthBattleMapUrl from '../../assets/images/battle/fifteenth-battle-map.webp';
|
||||
import firstBattleMapUrl from '../../assets/images/battle/first-battle-map.webp';
|
||||
import fortiethBattleMapUrl from '../../assets/images/battle/fortieth-battle-map.webp';
|
||||
import fortyEighthBattleMapUrl from '../../assets/images/battle/forty-eighth-battle-map.svg';
|
||||
import fortyEighthBattleMapUrl from '../../assets/images/battle/forty-eighth-battle-map.webp';
|
||||
import fortyFifthBattleMapUrl from '../../assets/images/battle/forty-fifth-battle-map.webp';
|
||||
import fortyFirstBattleMapUrl from '../../assets/images/battle/forty-first-battle-map.webp';
|
||||
import fortyFourthBattleMapUrl from '../../assets/images/battle/forty-fourth-battle-map.webp';
|
||||
import fortyNinthBattleMapUrl from '../../assets/images/battle/forty-ninth-battle-map.svg';
|
||||
import fortySecondBattleMapUrl from '../../assets/images/battle/forty-second-battle-map.webp';
|
||||
import fortySeventhBattleMapUrl from '../../assets/images/battle/forty-seventh-battle-map.svg';
|
||||
import fortySeventhBattleMapUrl from '../../assets/images/battle/forty-seventh-battle-map.webp';
|
||||
import fortySixthBattleMapUrl from '../../assets/images/battle/forty-sixth-battle-map.webp';
|
||||
import fortyThirdBattleMapUrl from '../../assets/images/battle/forty-third-battle-map.webp';
|
||||
import fourteenthBattleMapUrl from '../../assets/images/battle/fourteenth-battle-map.webp';
|
||||
|
||||