summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--scripts/make-jiangnan-art.py70
-rw-r--r--src/LivingVillage.Desktop/Assets/jiangnan-world.pngbin4468 -> 4492 bytes
-rw-r--r--src/LivingVillage.Desktop/VillageArt.fs23
3 files changed, 56 insertions, 37 deletions
diff --git a/scripts/make-jiangnan-art.py b/scripts/make-jiangnan-art.py
index f537942..f65390c 100644
--- a/scripts/make-jiangnan-art.py
+++ b/scripts/make-jiangnan-art.py
@@ -547,26 +547,34 @@ def build_world_atlas():
c.rect(x0 + 3, 23, 26, 6, (83, 52, 39, 255))
c.outline(x0, 0, 32, 32)
- # --- P26 house facade variant B: projecting eave, lattice window, courtyard gate.
+ # --- P26/P28 house facade variant B: projecting eave, tall lattice window, courtyard gate.
# Same baked-atlas pipeline as every other tile; the renderer only blits these cells.
+ # P28: variant B gets its own lighter blue-grey roof colour scale (variant A keeps the
+ # near-black 黛瓦脊), a portrait lattice window (A keeps a landscape window) and a green
+ # double-leaf courtyard gate, so the two facades stay legible when the whole 512 map is
+ # scaled to roughly 2px per tile.
- # slot(28) 屋檐挑出 (projecting eave): tiled roof band over an exposed wooden lip.
+ roof_b = (84, 106, 110, 255)
+ roof_b_light = (134, 158, 158, 255)
+ roof_b_dark = (56, 74, 80, 255)
+
+ # slot(28) 屋檐挑出 (projecting eave): light blue-grey tiled roof band + exposed wooden lip.
x0 = slot(28)
- c.rect(x0, 0, 32, 13, roof_dark)
+ c.rect(x0, 0, 32, 14, roof_b)
for x in range(0, 32, 8):
- c.rect(x0 + x, 0, 1, 13, roof)
+ c.rect(x0 + x, 0, 1, 14, roof_b_dark)
for x in range(4, 32, 8):
- c.rect(x0 + x, 0, 1, 13, roof)
- c.rect(x0, 2, 32, 1, roof_light)
- c.rect(x0, 12, 32, 1, roof)
- c.rect(x0, 13, 32, 3, wood)
- c.rect(x0, 13, 32, 1, wood_light)
- c.rect(x0, 15, 32, 1, wood_dark)
+ c.rect(x0 + x, 0, 1, 14, roof_b)
+ c.rect(x0, 2, 32, 2, roof_b_light)
+ c.rect(x0, 13, 32, 1, roof_b_dark)
+ c.rect(x0, 14, 32, 3, wood)
+ c.rect(x0, 14, 32, 1, wood_light)
+ c.rect(x0, 16, 32, 1, wood_dark)
for rx in (3, 10, 17, 24):
- c.rect(x0 + rx, 13, 2, 5, wood_dark)
- c.rect(x0, 18, 32, 4, (23, 31, 34, 80))
+ c.rect(x0 + rx, 14, 2, 4, wood_dark)
+ c.rect(x0, 17, 32, 4, (23, 31, 34, 80))
- # slot(29) 木格栅窗 (lattice window): wooden posts + fine grid muntins.
+ # slot(29) 木格栅窗 (lattice window): portrait frame with fine grid muntins.
x0 = slot(29)
c.rect(x0, 0, 32, 32, wall)
c.rect(x0, 0, 32, 3, wood)
@@ -576,32 +584,34 @@ def build_world_atlas():
c.rect(x0 + post_x, 0, 3, 32, wood)
c.rect(x0 + post_x, 0, 1, 32, wood_light)
c.rect(x0 + post_x + 2, 0, 1, 32, wood_dark)
- c.rect(x0 + 6, 7, 20, 18, (94, 66, 40, 255))
- c.rect(x0 + 8, 9, 16, 14, (61, 45, 49, 255))
- for lx in (12, 16, 20):
- c.rect(x0 + lx, 9, 1, 14, wall_seam)
- for ly in (14, 18):
- c.rect(x0 + 8, ly, 16, 1, wall_seam)
- c.rect(x0 + 6, 7, 20, 1, wood_light)
+ c.rect(x0 + 9, 5, 14, 22, (94, 66, 40, 255))
+ c.rect(x0 + 11, 7, 10, 18, (61, 45, 49, 255))
+ for lx in (13, 16, 19):
+ c.rect(x0 + lx, 7, 1, 18, wall_seam)
+ for ly in (11, 15, 19, 23):
+ c.rect(x0 + 11, ly, 10, 1, wall_seam)
+ c.rect(x0 + 9, 5, 14, 1, wood_light)
c.rect(x0 + 3, 28, 26, 4, (128, 128, 126, 255))
c.rect(x0 + 3, 28, 26, 1, (150, 150, 146, 255))
- # slot(30) 院门 (courtyard gate): tiled lintel cap, double doors, brass rings.
+ # slot(30) 院门 (courtyard gate): blue-grey lintel cap, green double doors, brass rings.
+ gate = (54, 88, 66, 255)
+ gate_light = (86, 128, 92, 255)
+ gate_dark = (36, 62, 46, 255)
x0 = slot(30)
c.rect(x0, 0, 32, 32, wall)
c.rect(x0, 0, 32, 3, wood)
c.rect(x0, 0, 32, 1, wood_light)
c.rect(x0, 3, 32, 1, wood_dark)
- c.rect(x0 + 3, 4, 26, 4, roof_dark)
- c.rect(x0 + 3, 4, 26, 1, roof_light)
- c.rect(x0 + 1, 8, 30, 2, roof)
- c.rect(x0 + 1, 9, 30, 1, roof_dark)
+ c.rect(x0 + 3, 4, 26, 4, roof_b)
+ c.rect(x0 + 3, 4, 26, 1, roof_b_light)
+ c.rect(x0 + 1, 8, 30, 2, roof_b_dark)
c.rect(x0 + 5, 10, 22, 18, (94, 66, 40, 255))
- c.rect(x0 + 7, 12, 18, 16, wood)
- c.rect(x0 + 7, 12, 18, 1, wood_light)
- c.rect(x0 + 15, 12, 2, 16, wood_dark)
- c.rect(x0 + 9, 15, 5, 4, wood_dark)
- c.rect(x0 + 18, 15, 5, 4, wood_dark)
+ c.rect(x0 + 7, 12, 18, 16, gate)
+ c.rect(x0 + 7, 12, 18, 1, gate_light)
+ c.rect(x0 + 15, 12, 2, 16, gate_dark)
+ c.rect(x0 + 8, 11, 7, 3, gate_dark)
+ c.rect(x0 + 18, 11, 6, 3, gate_light)
c.rect(x0 + 13, 20, 2, 2, (196, 158, 74, 255))
c.rect(x0 + 17, 20, 2, 2, (196, 158, 74, 255))
c.rect(x0 + 6, 28, 20, 3, (83, 52, 39, 255))
diff --git a/src/LivingVillage.Desktop/Assets/jiangnan-world.png b/src/LivingVillage.Desktop/Assets/jiangnan-world.png
index 11145a8..b67dd01 100644
--- a/src/LivingVillage.Desktop/Assets/jiangnan-world.png
+++ b/src/LivingVillage.Desktop/Assets/jiangnan-world.png
Binary files differ
diff --git a/src/LivingVillage.Desktop/VillageArt.fs b/src/LivingVillage.Desktop/VillageArt.fs
index d2fcc1a..9a56de4 100644
--- a/src/LivingVillage.Desktop/VillageArt.fs
+++ b/src/LivingVillage.Desktop/VillageArt.fs
@@ -612,7 +612,8 @@ module VillageArt =
spriteBatch.Draw(pixel, XnaRectangle(x, y, max 1 w, max 1 h), color)
/// P26 民居立面变体:按位置确定性交替两种立面(沿河沿路分布)。
- /// 0 = 黛瓦脊 + 木墙/窗 + 门(P24 原样);1 = 挑檐挑出 + 木格栅窗 + 院门。
+ /// 0 = 黛瓦脊 + 木墙/窗 + 门(P24 原样);1 = 亮青灰挑檐(多叠一层、向两侧各出一格)+
+ /// 竖长木格栅窗 + 绿院门(P28 强化配色与轮廓,保证 512 整图 ~2px/tile 下两变体可分)。
/// 纯函数、不改变任何瓦片/可达性语义;64x48 与 256x192 的 tiles checksum 不受影响。
let houseFacadeVariant (building: MapGen.Building) : int =
let remainder = (building.Left + building.Top) % 2
@@ -649,14 +650,22 @@ module VillageArt =
else WallWoodSprite
drawCell wallSprite x building.DoorY
| _ ->
- // 变体 B(P26):挑檐向两侧各出一格 + 木格栅窗 + 院门。
- for x in (left - 1) .. (right + 1) do
- drawCell RoofEaveOverhangSprite x building.Top
+ // 变体 B(P26/P28):亮青灰挑檐向两侧各出一格 + 竖长木格栅窗 + 绿院门。
+ // P28 再向上叠一层挑檐,使 B 的轮廓比 A 高一格;水面之上不叠,避免屋顶压水。
+ let isWater x y =
+ x >= 0 && x < map.Width && y >= 0 && y < map.Height
+ && map.Tiles.[y * map.Width + x] = int MapGen.GroundTile.Water
+ for row in building.Top .. building.DoorY - 1 do
+ for x in (left - 1) .. (right + 1) do
+ drawCell RoofEaveOverhangSprite x row
+ let upper = building.Top - 1
+ if upper >= 0 then
+ for x in (left - 1) .. (right + 1) do
+ if not (isWater x upper) then
+ drawCell RoofEaveOverhangSprite x upper
for x in left .. right do
let wallSprite =
- if x = building.DoorX then CourtyardDoorSprite
- elif (x - left) % 2 = 0 then WallLatticeSprite
- else WallWoodSprite
+ if x = building.DoorX then CourtyardDoorSprite else WallLatticeSprite
drawCell wallSprite x building.DoorY
// P26 河岸装饰:护岸石垒 / 芦苇 / 垂柳(垂柳占上下两格),只在大图生成。
for decoration in map.Decorations do