summaryrefslogtreecommitdiff
path: root/src/LivingVillage.Desktop/VillageArt.fs
diff options
context:
space:
mode:
authorSomhairle H. Marisol <[email protected]>2026-09-29 05:42:36 +0800
committerSomhairle H. Marisol <[email protected]>2026-09-29 05:42:36 +0800
commit4971a2ada6db9a37807bf46a29dbea3d9edbf06a (patch)
tree2fa44306526fe26d0d6c9b88c63bf357844508f5 /src/LivingVillage.Desktop/VillageArt.fs
parent1354745258f08fae0eea2c599b59fbbfb3254dbd (diff)
downloadliving-village-4971a2ada6db9a37807bf46a29dbea3d9edbf06a.tar.gz
p64: A3 样板三处视觉雕琢(俯瞰上半补种/桥栏杆与护岸石/内景家具)+ 证据
Diffstat (limited to 'src/LivingVillage.Desktop/VillageArt.fs')
-rw-r--r--src/LivingVillage.Desktop/VillageArt.fs65
1 files changed, 62 insertions, 3 deletions
diff --git a/src/LivingVillage.Desktop/VillageArt.fs b/src/LivingVillage.Desktop/VillageArt.fs
index 3dbb8d4..031b577 100644
--- a/src/LivingVillage.Desktop/VillageArt.fs
+++ b/src/LivingVillage.Desktop/VillageArt.fs
@@ -58,6 +58,11 @@ module VillageArt =
| Table
| Bed
| Screen
+ // P64 内景下半部家具补件(椅/凳/床尾凳/壶)。
+ | Chair
+ | Stool
+ | BedFoot
+ | Teapot
type InteriorElement =
{ Kind: InteriorElementKind
@@ -210,7 +215,10 @@ module VillageArt =
{ Origin = position 25 18
Grounds =
- [ ground StonePath 3 5
+ // P64 北侧田埂小径:衔接上方补种的菜畦/竹丛,填充样板区上半部空旷。
+ [ for x in 0 .. 19 do
+ ground StonePath x 0
+ ground StonePath 3 5
ground StonePath 4 5
ground StonePath 5 5
ground StonePath 6 5
@@ -256,13 +264,30 @@ module VillageArt =
renderProp StoneLantern 4 14
renderProp StoneLantern 16 14
renderProp WaterVat 12 11
- renderProp MarketStall 3 11 ]
+ renderProp MarketStall 3 11
+ // P64 样板区上半部(local y 0..6)中密度补种:菜畦/竹丛/灌木/花丛,
+ // 全部复用既有 RenderPropKind 与低饱和配色,非几何占位。
+ renderProp VegetablePatch 1 1
+ renderProp VegetablePatch 10 2
+ renderProp VegetablePatch 14 1
+ renderProp VegetablePatch 16 4
+ renderProp BambooGrove 8 3
+ renderProp BambooGrove 18 2
+ renderProp ShrubPatch 0 5
+ renderProp ShrubPatch 12 5
+ renderProp FlowerBush 2 3
+ renderProp FlowerBush 6 1 ]
Interior =
{ Elements =
[ interiorElement Window 2 2
interiorElement Table 4 4
interiorElement Bed 7 3
- interiorElement Screen 7 6 ] } }
+ interiorElement Screen 7 6
+ // P64 内景下半部家具补件:椅/凳/床尾凳/柜旁壶。
+ interiorElement BedFoot 5 4
+ interiorElement Chair 2 5
+ interiorElement Stool 6 5
+ interiorElement Teapot 4 5 ] } }
let worldTile (plan: JiangnanRenderPlan) (localPosition: TilePosition) : TilePosition =
{ X = plan.Origin.X + localPosition.X
@@ -294,6 +319,19 @@ module VillageArt =
| MarketStall -> [ position x y ])
|> many
+ /// P64 河埠/护岸石偏移(相对桥首格):桥两侧水线各铺一块,强化桥与河岸的衔接。
+ /// 只做视觉叠加,不写入 footprint、不改瓦片/通行。
+ let bridgeAbutmentOffsets : (int * int) list =
+ [ (-1, 1); (1, 1); (-1, 2); (1, 2) ]
+
+ /// 样板桥两侧护岸石的世界坐标(纯函数,供绘制与回归共用)。
+ let sampleBridgeAbutmentTiles (plan: JiangnanRenderPlan) : TilePosition list =
+ plan.Props
+ |> List.filter (fun prop -> prop.Kind = Bridge)
+ |> List.collect (fun prop ->
+ bridgeAbutmentOffsets
+ |> List.map (fun (dx, dy) -> worldTile plan { X = prop.Position.X + dx; Y = prop.Position.Y + dy }))
+
let private positiveModulo divisor value =
let remainder = value % divisor
if remainder < 0 then remainder + divisor else remainder
@@ -1175,6 +1213,13 @@ module VillageArt =
match textures.Cc0TileAtlas with
| Some _ -> drawCc0At p cc0TileIndexRailing
| None -> draw p BridgeSprite
+ // P64 河埠/护岸石:仅江南图集下于桥两侧水线补石,增强桥的可读性;
+ // cc0 模式保持原样,不改位置/通行。
+ match textures.Cc0TileAtlas with
+ | Some _ -> ()
+ | None ->
+ for (dx, dy) in bridgeAbutmentOffsets do
+ draw (offsetTile position dx dy) RevetmentStoneSprite
bridgeTile position
bridgeTile (offsetTile position 0 1)
bridgeTile (offsetTile position 0 2)
@@ -1368,6 +1413,11 @@ module VillageArt =
| Table -> XnaRectangle(112, 48, 64, 48)
| Bed -> XnaRectangle(176, 0, 48, 96)
| Screen -> XnaRectangle(224, 0, 32, 96)
+ // P64 补件:坐标与 scripts/make-jiangnan-art.py 的绘制区间一一对应。
+ | Chair -> XnaRectangle(4, 8, 28, 44)
+ | Stool -> XnaRectangle(36, 14, 24, 22)
+ | BedFoot -> XnaRectangle(262, 4, 56, 18)
+ | Teapot -> XnaRectangle(330, 6, 20, 16)
let interiorLayout (viewportWidth: int) (viewportHeight: int) : InteriorLayout =
{ RoomX = 40
@@ -1442,6 +1492,15 @@ module VillageArt =
XnaRectangle(layout.RoomX + element.Position.X * Sim.tilePixels - 8, baseY - 96, 48, 96)
| Screen ->
XnaRectangle(layout.RoomX + element.Position.X * Sim.tilePixels, baseY - 96, 32, 96)
+ // P64 补件按其像素体量落位(低矮家具贴近地面线)。
+ | Chair ->
+ XnaRectangle(layout.RoomX + element.Position.X * Sim.tilePixels - 8, baseY - 44, 28, 44)
+ | Stool ->
+ XnaRectangle(layout.RoomX + element.Position.X * Sim.tilePixels - 8, baseY - 22, 24, 22)
+ | BedFoot ->
+ XnaRectangle(layout.RoomX + element.Position.X * Sim.tilePixels - 16, baseY - 14, 56, 18)
+ | Teapot ->
+ XnaRectangle(layout.RoomX + element.Position.X * Sim.tilePixels - 8, baseY - 16, 20, 16)
for element in plan.Elements |> List.sortBy (fun element -> element.Position.Y, element.Position.X) do
spriteBatch.Draw(textures.InteriorAtlas, elementDestination element, interiorSourceRectangle element.Kind, tint)