From d3c0ef17cb1c4d30c1d586e2a5b616f58bd3d875 Mon Sep 17 00:00:00 2001 From: "Somhairle H. Marisol" Date: Tue, 22 Sep 2026 02:43:39 +0800 Subject: feat(mapgen): 河道连续性不变量 + 桥/石板路网/沿河民居(P20 第二步) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 河道改为贯穿全图连续水带(每列一段、宽度 >= RiverWidth),置于核心区上下 两侧且不相交;新增不变量测试:逐列水段数恒定、每段宽度下限、任意水格 >=2 个水邻居(禁止断裂缺口与孤立水点)。 - Result 新增 Rivers/Bridges/Paths/Buildings/BridgeCrossingsOk;每河 2 座桥、 横贯主路 + 垂直连接路 + 远岸路 + 白墙黑瓦民居(门朝路)。 - 公开 isWalkable/floodFill;ReachabilityOk 现覆盖 30 spawn + 所有门 + 所有桥面, BridgeCrossingsOk 保证每桥两岸同连通域。 - 回归:Desktop 115->119、Kernel 90 不变;final_digest 与基线一致。 --- src/LivingVillage.Desktop/VillageArt.fs | 40 ++++++++++++++++++++++++++++----- 1 file changed, 34 insertions(+), 6 deletions(-) (limited to 'src/LivingVillage.Desktop/VillageArt.fs') diff --git a/src/LivingVillage.Desktop/VillageArt.fs b/src/LivingVillage.Desktop/VillageArt.fs index 51e17e0..19c9aa6 100644 --- a/src/LivingVillage.Desktop/VillageArt.fs +++ b/src/LivingVillage.Desktop/VillageArt.fs @@ -724,9 +724,34 @@ module VillageArt = /// P20 证据用:把整张 MapGen 地图等比缩放到视口内绘制,返回绘制的瓦片数。 /// 仅用于 `LV_MAPGEN_SHOT` 整图取证,不参与正常游戏循环。 + let private fillRect (spriteBatch: SpriteBatch) (pixel: Texture2D) (color: XnaColor) (x: int) (y: int) (w: int) (h: int) = + spriteBatch.Draw(pixel, XnaRectangle(x, y, max 1 w, max 1 h), color) + + /// 整图证据里叠加桥面与沿河民居(白墙黑瓦色块 + 门)。 + let private drawMapStructures + (spriteBatch: SpriteBatch) + (textures: ArtTextures) + (pixel: Texture2D) + (tileX: int -> int) + (tileY: int -> int) + (cell: int) + (map: MapGen.Result) = + let bridgeSource = tileSourceRectangle BridgeSprite + for (x, y) in map.Bridges do + spriteBatch.Draw(textures.TileAtlas, XnaRectangle(tileX x, tileY y, cell, cell), bridgeSource, XnaColor.White) + for building in map.Buildings do + for row in building.Top .. building.Top + building.Height - 1 do + // 白墙朝向道路一行(门所在行),其余为黑瓦屋顶,两侧河岸朝向一致。 + let color = + if row = building.DoorY then XnaColor(236, 232, 220) + else XnaColor(48, 52, 60) + fillRect spriteBatch pixel color (tileX building.Left) (tileY row) (building.Width * cell) (cell) + fillRect spriteBatch pixel (XnaColor(96, 60, 42)) (tileX building.DoorX) (tileY building.DoorY) cell cell + let drawMapFitted (spriteBatch: SpriteBatch) (textures: ArtTextures) + (pixel: Texture2D) (viewportWidth: int) (viewportHeight: int) (map: MapGen.Result) @@ -737,6 +762,8 @@ module VillageArt = let cell = max 1 (int (float32 Sim.tilePixels * scale)) let offsetX = (viewportWidth - map.Width * cell) / 2 let offsetY = (viewportHeight - map.Height * cell) / 2 + let tileX x = offsetX + x * cell + let tileY y = offsetY + y * cell let spriteOf code = match code with | 1 -> WaterSprite @@ -746,13 +773,15 @@ module VillageArt = for y in 0 .. map.Height - 1 do for x in 0 .. map.Width - 1 do let code = map.Tiles.[y * map.Width + x] - spriteBatch.Draw(textures.TileAtlas, XnaRectangle(offsetX + x * cell, offsetY + y * cell, cell, cell), tileSourceRectangle (spriteOf code), tint) + spriteBatch.Draw(textures.TileAtlas, XnaRectangle(tileX x, tileY y, cell, cell), tileSourceRectangle (spriteOf code), tint) + drawMapStructures spriteBatch textures pixel tileX tileY cell map map.Width * map.Height /// P20 证据用:按相机做视口裁剪,只绘制可见瓦片(1:1 像素),返回实际绘制数。 let drawMapViewport (spriteBatch: SpriteBatch) (textures: ArtTextures) + (pixel: Texture2D) (camera: XnaVector2) (viewportWidth: int) (viewportHeight: int) @@ -761,6 +790,8 @@ module VillageArt = (tint: XnaColor) : int = let x0, y0, x1, y1 = MapGen.visibleTileRange map.Width map.Height (int camera.X) (int camera.Y) viewportWidth viewportHeight + let tileX x = x * Sim.tilePixels - int camera.X + let tileY y = y * Sim.tilePixels - int camera.Y let spriteOf (x: int) (y: int) code = match code with | 1 -> @@ -775,12 +806,9 @@ module VillageArt = for y in y0 .. y1 do for x in x0 .. x1 do let code = map.Tiles.[y * map.Width + x] - spriteBatch.Draw( - textures.TileAtlas, - XnaRectangle(x * Sim.tilePixels - int camera.X, y * Sim.tilePixels - int camera.Y, Sim.tilePixels, Sim.tilePixels), - tileSourceRectangle (spriteOf x y code), - tint) + spriteBatch.Draw(textures.TileAtlas, XnaRectangle(tileX x, tileY y, Sim.tilePixels, Sim.tilePixels), tileSourceRectangle (spriteOf x y code), tint) drawn <- drawn + 1 + drawMapStructures spriteBatch textures pixel tileX tileY Sim.tilePixels map drawn let drawCharacter -- cgit v1.2.3