Replace battle maps 61 and 62 with hand-painted assets
@@ -2,7 +2,7 @@
|
||||
|
||||
## Scope
|
||||
|
||||
The first sixty 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 sixty-two 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
|
||||
|
||||
@@ -91,6 +91,8 @@ python scripts/generate-handpaint-map-sample.py --map fifty-seventh --webp-quali
|
||||
python scripts/generate-handpaint-map-sample.py --map fifty-eighth --webp-quality 90
|
||||
python scripts/generate-handpaint-map-sample.py --map fifty-ninth --webp-quality 90
|
||||
python scripts/generate-handpaint-map-sample.py --map sixtieth --webp-quality 90
|
||||
python scripts/generate-handpaint-map-sample.py --map sixty-first --webp-quality 90
|
||||
python scripts/generate-handpaint-map-sample.py --map sixty-second --webp-quality 90
|
||||
```
|
||||
|
||||
Comparison example:
|
||||
@@ -161,6 +163,8 @@ python scripts/generate-handpaint-map-sample.py --map thirtieth --tile-size 192
|
||||
- `src/assets/images/battle/fifty-eighth-battle-map.webp`
|
||||
- `src/assets/images/battle/fifty-ninth-battle-map.webp`
|
||||
- `src/assets/images/battle/sixtieth-battle-map.webp`
|
||||
- `src/assets/images/battle/sixty-first-battle-map.webp`
|
||||
- `src/assets/images/battle/sixty-second-battle-map.webp`
|
||||
|
||||
## QA Outputs
|
||||
|
||||
@@ -282,5 +286,9 @@ python scripts/generate-handpaint-map-sample.py --map thirtieth --tile-size 192
|
||||
- `docs/fifty-ninth-battle-map-handpaint-preview.png`
|
||||
- `docs/sixtieth-battle-map-handpaint-before-after.png`
|
||||
- `docs/sixtieth-battle-map-handpaint-preview.png`
|
||||
- `docs/sixty-first-battle-map-handpaint-before-after.png`
|
||||
- `docs/sixty-first-battle-map-handpaint-preview.png`
|
||||
- `docs/sixty-second-battle-map-handpaint-before-after.png`
|
||||
- `docs/sixty-second-battle-map-handpaint-preview.png`
|
||||
|
||||
Browser screenshots are saved per verification run after build/deploy.
|
||||
|
||||
BIN
docs/sixty-first-battle-map-handpaint-before-after.png
Normal file
|
After Width: | Height: | Size: 3.2 MiB |
BIN
docs/sixty-first-battle-map-handpaint-preview.png
Normal file
|
After Width: | Height: | Size: 2.6 MiB |
BIN
docs/sixty-second-battle-map-handpaint-before-after.png
Normal file
|
After Width: | Height: | Size: 3.3 MiB |
BIN
docs/sixty-second-battle-map-handpaint-preview.png
Normal file
|
After Width: | Height: | Size: 2.7 MiB |
@@ -603,6 +603,26 @@ MAP_CONFIGS = {
|
||||
"seed": 241294,
|
||||
"tile_size": IMMENSE_LARGE_MAP_TILE_SIZE,
|
||||
},
|
||||
"sixty-first": {
|
||||
"slug": "sixty-first-battle-map",
|
||||
"terrain_export": "sixtyFirstBattleMap",
|
||||
"units_export": "sixtyFirstBattleUnits",
|
||||
"ally_positions_export": "sixtyFirstBattleAllyPositions",
|
||||
"out": BATTLE_IMAGE_DIR / "sixty-first-battle-map.webp",
|
||||
"before": BATTLE_IMAGE_DIR / "sixty-first-battle-map.svg",
|
||||
"seed": 241304,
|
||||
"tile_size": IMMENSE_LARGE_MAP_TILE_SIZE,
|
||||
},
|
||||
"sixty-second": {
|
||||
"slug": "sixty-second-battle-map",
|
||||
"terrain_export": "sixtySecondBattleMap",
|
||||
"units_export": "sixtySecondBattleUnits",
|
||||
"ally_positions_export": "sixtySecondBattleAllyPositions",
|
||||
"out": BATTLE_IMAGE_DIR / "sixty-second-battle-map.webp",
|
||||
"before": BATTLE_IMAGE_DIR / "sixty-second-battle-map.svg",
|
||||
"seed": 241314,
|
||||
"tile_size": IMMENSE_LARGE_MAP_TILE_SIZE,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1952 1664" role="img" aria-labelledby="title desc">
|
||||
<title id="title">Hanzhong rainy pass defense map</title>
|
||||
<desc id="desc">Original tactical battlefield map with rainy Hanzhong passes, commandery supply roads, Shu granary camps, Wei columns, forests, rivers, and mountain forts.</desc>
|
||||
<defs>
|
||||
<linearGradient id="ground" x1="0" x2="1" y1="0" y2="1">
|
||||
<stop offset="0" stop-color="#40564b"/>
|
||||
<stop offset="0.48" stop-color="#66785b"/>
|
||||
<stop offset="1" stop-color="#9c895d"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="rainRiver" x1="0" x2="1" y1="0" y2="1">
|
||||
<stop offset="0" stop-color="#244e63"/>
|
||||
<stop offset="0.55" stop-color="#3d7b85"/>
|
||||
<stop offset="1" stop-color="#8bb8aa"/>
|
||||
</linearGradient>
|
||||
<filter id="grain" x="-10%" y="-10%" width="120%" height="120%">
|
||||
<feTurbulence type="fractalNoise" baseFrequency="0.014" numOctaves="3" seed="61"/>
|
||||
<feColorMatrix type="saturate" values="0.16"/>
|
||||
<feBlend mode="multiply" in2="SourceGraphic"/>
|
||||
</filter>
|
||||
<filter id="rainBlur" x="-4%" y="-4%" width="108%" height="108%">
|
||||
<feGaussianBlur stdDeviation="1.2"/>
|
||||
</filter>
|
||||
</defs>
|
||||
<rect width="1952" height="1664" fill="url(#ground)"/>
|
||||
<path d="M72 118 C254 246 216 406 424 558 C606 692 560 882 790 1010 C1010 1134 982 1304 1216 1444 C1410 1562 1594 1586 1888 1608" fill="none" stroke="url(#rainRiver)" stroke-width="92" stroke-linecap="round"/>
|
||||
<path d="M998 0 C942 164 1032 330 944 492 C858 650 950 824 882 990 C812 1162 860 1300 746 1518" fill="none" stroke="#2c6775" stroke-width="60" stroke-linecap="round" opacity="0.9"/>
|
||||
<path d="M260 1440 C448 1276 616 1228 812 1090 C1002 956 1234 948 1418 784 C1594 626 1696 496 1900 438" fill="none" stroke="#d0b173" stroke-width="44" stroke-linecap="round"/>
|
||||
<path d="M110 1330 C346 1292 526 1182 690 1042 C870 886 1082 842 1272 684 C1480 510 1642 356 1904 236" fill="none" stroke="#b6915d" stroke-width="30" stroke-linecap="round"/>
|
||||
<path d="M372 1510 C540 1358 696 1290 882 1162 C1066 1036 1264 1058 1448 902 C1628 746 1708 612 1904 578" fill="none" stroke="#c49b64" stroke-width="28" stroke-linecap="round"/>
|
||||
<g fill="#344433" opacity="0.9">
|
||||
<path d="M0 0 L476 0 L356 206 L496 402 L250 506 L0 414 Z"/>
|
||||
<path d="M634 0 L990 0 L902 246 L716 370 L580 198 Z"/>
|
||||
<path d="M1130 0 L1952 0 L1952 348 L1776 294 L1554 394 L1370 222 Z"/>
|
||||
<path d="M1510 584 L1952 488 L1952 1004 L1708 914 L1466 976 Z"/>
|
||||
<path d="M0 580 L420 650 L256 896 L438 1128 L0 1206 Z"/>
|
||||
</g>
|
||||
<g fill="#23382e" opacity="0.74">
|
||||
<ellipse cx="286" cy="734" rx="222" ry="150"/>
|
||||
<ellipse cx="564" cy="962" rx="210" ry="132"/>
|
||||
<ellipse cx="1270" cy="1186" rx="292" ry="150"/>
|
||||
<ellipse cx="1558" cy="1074" rx="218" ry="118"/>
|
||||
<ellipse cx="1040" cy="674" rx="222" ry="124"/>
|
||||
</g>
|
||||
<g fill="#7a6046" stroke="#322821" stroke-width="8">
|
||||
<rect x="226" y="1324" width="240" height="138" rx="6"/>
|
||||
<rect x="574" y="1140" width="260" height="150" rx="6"/>
|
||||
<rect x="938" y="952" width="272" height="154" rx="6"/>
|
||||
<rect x="1288" y="704" width="298" height="168" rx="6"/>
|
||||
<rect x="1604" y="374" width="260" height="154" rx="6"/>
|
||||
</g>
|
||||
<g fill="#603f34" stroke="#281f19" stroke-width="10">
|
||||
<path d="M1362 448 L1574 404 L1694 526 L1628 678 L1400 700 L1282 572 Z"/>
|
||||
<path d="M900 682 L1110 642 L1236 760 L1172 910 L954 938 L830 806 Z"/>
|
||||
<path d="M1516 188 L1740 160 L1880 268 L1810 410 L1588 438 L1460 316 Z"/>
|
||||
<path d="M1096 1162 L1292 1132 L1420 1242 L1364 1378 L1140 1398 L1018 1284 Z"/>
|
||||
</g>
|
||||
<g fill="#deca92" stroke="#59442f" stroke-width="7">
|
||||
<rect x="148" y="1234" width="118" height="78" rx="5"/>
|
||||
<rect x="478" y="1074" width="124" height="80" rx="5"/>
|
||||
<rect x="720" y="924" width="128" height="82" rx="5"/>
|
||||
<rect x="1176" y="808" width="134" height="86" rx="5"/>
|
||||
<rect x="1400" y="544" width="128" height="82" rx="5"/>
|
||||
</g>
|
||||
<g opacity="0.26" stroke="#d8e2da" stroke-width="3" stroke-linecap="round" filter="url(#rainBlur)">
|
||||
<path d="M144 0 L60 180"/>
|
||||
<path d="M360 0 L270 210"/>
|
||||
<path d="M590 0 L496 226"/>
|
||||
<path d="M820 0 L720 248"/>
|
||||
<path d="M1050 0 L948 236"/>
|
||||
<path d="M1280 0 L1168 258"/>
|
||||
<path d="M1510 0 L1398 246"/>
|
||||
<path d="M1740 0 L1620 258"/>
|
||||
<path d="M1940 60 L1810 326"/>
|
||||
</g>
|
||||
<g fill="#efe1ab" font-family="serif" font-size="46" font-weight="700" stroke="#35261d" stroke-width="2" paint-order="stroke">
|
||||
<text x="250" y="1406">촉 창고</text>
|
||||
<text x="624" y="1224">무도 보급로</text>
|
||||
<text x="984" y="1042">한중 북문</text>
|
||||
<text x="1346" y="806">사마의 별동대</text>
|
||||
<text x="1602" y="474">조진 본영</text>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 4.7 KiB |
BIN
src/assets/images/battle/sixty-first-battle-map.webp
Normal file
|
After Width: | Height: | Size: 20 MiB |
@@ -1,91 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1984 1696" role="img" aria-labelledby="title desc">
|
||||
<title id="title">Qishan renewed offensive map</title>
|
||||
<desc id="desc">Original tactical battlefield map with renewed Qishan roads, Lucheng forts, Shu supply camps, Wei delay lines, rivers, forests, ridges, and cliff gates.</desc>
|
||||
<defs>
|
||||
<linearGradient id="ground" x1="0" x2="1" y1="0" y2="1">
|
||||
<stop offset="0" stop-color="#445343"/>
|
||||
<stop offset="0.42" stop-color="#6f7652"/>
|
||||
<stop offset="1" stop-color="#9d8358"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="river" x1="0" x2="1" y1="0" y2="1">
|
||||
<stop offset="0" stop-color="#25465d"/>
|
||||
<stop offset="0.5" stop-color="#3f7483"/>
|
||||
<stop offset="1" stop-color="#8eb1a4"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="road" x1="0" x2="1" y1="0" y2="0">
|
||||
<stop offset="0" stop-color="#c49a62"/>
|
||||
<stop offset="0.5" stop-color="#dfc07c"/>
|
||||
<stop offset="1" stop-color="#a9784f"/>
|
||||
</linearGradient>
|
||||
<filter id="grain" x="-10%" y="-10%" width="120%" height="120%">
|
||||
<feTurbulence type="fractalNoise" baseFrequency="0.012" numOctaves="4" seed="62"/>
|
||||
<feColorMatrix type="saturate" values="0.18"/>
|
||||
<feBlend mode="multiply" in2="SourceGraphic"/>
|
||||
</filter>
|
||||
<filter id="soft" x="-4%" y="-4%" width="108%" height="108%">
|
||||
<feGaussianBlur stdDeviation="1.4"/>
|
||||
</filter>
|
||||
</defs>
|
||||
<rect width="1984" height="1696" fill="url(#ground)"/>
|
||||
<path d="M88 122 C318 258 258 472 506 626 C732 768 678 982 948 1128 C1210 1266 1208 1430 1462 1542 C1650 1626 1816 1650 1918 1668" fill="none" stroke="url(#river)" stroke-width="88" stroke-linecap="round"/>
|
||||
<path d="M1048 0 C1000 180 1082 352 1004 522 C922 704 1044 864 956 1050 C878 1212 908 1390 790 1618" fill="none" stroke="#2c6875" stroke-width="54" stroke-linecap="round" opacity="0.92"/>
|
||||
<path d="M146 1458 C390 1308 612 1260 818 1102 C1032 938 1294 906 1498 714 C1688 534 1790 382 1940 292" fill="none" stroke="url(#road)" stroke-width="46" stroke-linecap="round"/>
|
||||
<path d="M178 1308 C412 1242 592 1118 750 950 C942 746 1170 754 1390 586 C1588 434 1754 310 1948 178" fill="none" stroke="#b48758" stroke-width="30" stroke-linecap="round"/>
|
||||
<path d="M490 1560 C604 1398 742 1324 950 1196 C1152 1070 1374 1082 1544 920 C1714 758 1806 596 1948 548" fill="none" stroke="#d3aa68" stroke-width="30" stroke-linecap="round"/>
|
||||
<path d="M706 1148 C828 1012 894 872 1030 736 C1166 600 1334 506 1518 372" fill="none" stroke="#e3c17b" stroke-width="24" stroke-linecap="round" opacity="0.95"/>
|
||||
<g fill="#324432" opacity="0.92">
|
||||
<path d="M0 0 L500 0 L374 214 L520 414 L268 526 L0 424 Z"/>
|
||||
<path d="M630 0 L1036 0 L932 258 L732 386 L584 204 Z"/>
|
||||
<path d="M1168 0 L1984 0 L1984 334 L1786 282 L1566 396 L1378 226 Z"/>
|
||||
<path d="M1514 560 L1984 462 L1984 1018 L1716 918 L1462 990 Z"/>
|
||||
<path d="M0 598 L428 658 L260 930 L452 1150 L0 1232 Z"/>
|
||||
</g>
|
||||
<g fill="#22372e" opacity="0.78">
|
||||
<ellipse cx="294" cy="748" rx="238" ry="152"/>
|
||||
<ellipse cx="588" cy="1000" rx="224" ry="138"/>
|
||||
<ellipse cx="1228" cy="1226" rx="310" ry="154"/>
|
||||
<ellipse cx="1590" cy="1084" rx="236" ry="128"/>
|
||||
<ellipse cx="1042" cy="654" rx="252" ry="132"/>
|
||||
<ellipse cx="1446" cy="446" rx="196" ry="104"/>
|
||||
</g>
|
||||
<g fill="#755c42" stroke="#30251d" stroke-width="8">
|
||||
<rect x="238" y="1340" width="250" height="142" rx="6"/>
|
||||
<rect x="574" y="1160" width="270" height="154" rx="6"/>
|
||||
<rect x="946" y="978" width="282" height="158" rx="6"/>
|
||||
<rect x="1290" y="742" width="310" height="174" rx="6"/>
|
||||
<rect x="1620" y="402" width="274" height="160" rx="6"/>
|
||||
</g>
|
||||
<g fill="#593d34" stroke="#241c17" stroke-width="10">
|
||||
<path d="M1376 414 L1600 380 L1734 504 L1676 670 L1442 706 L1304 574 Z"/>
|
||||
<path d="M926 670 L1146 628 L1274 748 L1214 922 L978 952 L850 808 Z"/>
|
||||
<path d="M1540 152 L1770 126 L1912 242 L1850 394 L1618 430 L1474 302 Z"/>
|
||||
<path d="M1112 1184 L1322 1154 L1452 1272 L1392 1414 L1156 1438 L1034 1300 Z"/>
|
||||
</g>
|
||||
<g fill="#e2ca8f" stroke="#59442f" stroke-width="7">
|
||||
<rect x="164" y="1244" width="122" height="82" rx="5"/>
|
||||
<rect x="484" y="1084" width="130" height="84" rx="5"/>
|
||||
<rect x="738" y="930" width="136" height="86" rx="5"/>
|
||||
<rect x="1184" y="826" width="144" height="90" rx="5"/>
|
||||
<rect x="1418" y="556" width="134" height="86" rx="5"/>
|
||||
</g>
|
||||
<g opacity="0.23" stroke="#eef0dc" stroke-width="4" stroke-linecap="round" filter="url(#soft)">
|
||||
<path d="M120 230 C300 188 424 190 604 238"/>
|
||||
<path d="M710 420 C876 372 1058 382 1238 440"/>
|
||||
<path d="M1140 150 C1300 112 1486 126 1658 176"/>
|
||||
<path d="M1264 1018 C1430 986 1608 998 1814 1054"/>
|
||||
</g>
|
||||
<g fill="#d9b869" stroke="#4a3322" stroke-width="5">
|
||||
<circle cx="318" cy="1352" r="22"/>
|
||||
<circle cx="384" cy="1378" r="18"/>
|
||||
<circle cx="642" cy="1188" r="20"/>
|
||||
<circle cx="1038" cy="1000" r="22"/>
|
||||
<circle cx="1368" cy="762" r="20"/>
|
||||
<circle cx="1708" cy="418" r="22"/>
|
||||
</g>
|
||||
<g opacity="0.58" fill="#7b2f2d">
|
||||
<path d="M314 1290 l56 16 -56 16 z"/>
|
||||
<path d="M650 1130 l60 18 -60 18 z"/>
|
||||
<path d="M1048 946 l64 18 -64 18 z"/>
|
||||
<path d="M1400 704 l64 20 -64 20 z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 5.1 KiB |
BIN
src/assets/images/battle/sixty-second-battle-map.webp
Normal file
|
After Width: | Height: | Size: 22 MiB |
@@ -10,8 +10,8 @@ import fiftyFifthBattleMapUrl from '../../assets/images/battle/fifty-fifth-battl
|
||||
import fiftyEighthBattleMapUrl from '../../assets/images/battle/fifty-eighth-battle-map.webp';
|
||||
import fiftyNinthBattleMapUrl from '../../assets/images/battle/fifty-ninth-battle-map.webp';
|
||||
import sixtiethBattleMapUrl from '../../assets/images/battle/sixtieth-battle-map.webp';
|
||||
import sixtyFirstBattleMapUrl from '../../assets/images/battle/sixty-first-battle-map.svg';
|
||||
import sixtySecondBattleMapUrl from '../../assets/images/battle/sixty-second-battle-map.svg';
|
||||
import sixtyFirstBattleMapUrl from '../../assets/images/battle/sixty-first-battle-map.webp';
|
||||
import sixtySecondBattleMapUrl from '../../assets/images/battle/sixty-second-battle-map.webp';
|
||||
import sixtyThirdBattleMapUrl from '../../assets/images/battle/sixty-third-battle-map.svg';
|
||||
import sixtyFourthBattleMapUrl from '../../assets/images/battle/sixty-fourth-battle-map.svg';
|
||||
import sixtyFifthBattleMapUrl from '../../assets/images/battle/sixty-fifth-battle-map.svg';
|
||||
|
||||