diff options
| author | Somhairle H. Marisol <[email protected]> | 2026-09-22 12:41:06 +0800 |
|---|---|---|
| committer | Somhairle H. Marisol <[email protected]> | 2026-09-22 12:41:06 +0800 |
| commit | 92bcc9b9fc4eeea4f11913a0de2a34811b262dfd (patch) | |
| tree | 7fa25b2a3fc2ebeea7b2fe2cbc6285848d7c0a26 /src/LivingVillage.Desktop/VillageArt.fs | |
| parent | 4034f55ee0b9cbd8c9db5f850e10e21e15fb7274 (diff) | |
| download | living-village-92bcc9b9fc4eeea4f11913a0de2a34811b262dfd.tar.gz | |
feat(desktop): P30 512 民居增密 + 乡村空区填充 + 主路柔化
- MapGen(仅大图尺寸自适应分支,默认 64x48/256x192 不进入、不消费额外 RNG):
① ExtraRiversideHouses 16 -> 30,组团 2-5 座;含基础岸屋的路段优先布组并为每座孤立
基础民居贴格配对,placeGroup 试排后按「与既有/同组民居足迹间隙 <=2」过滤,孤立单屋不落地。
512 seed4242:组团民居 24 -> 45,规模 [5;4x6;3x2;2x3],0 组 <2 座。
② 新增 GroundTile.PaddyField=4/VegetablePlot=5(成熟 tile;非水可通行)+ Result.Groves
(纯视觉)+ Result.Farmhouses(门贴院落路、计入 BFS);18x14 确定性网格铺田块/树丛/农舍,
离水 >=3 格、避开路网/核心/民居。草地瓦片 96.3% -> 83.9%,水田 11595 + 菜畦 12877 格。
③ Result.MainRoadCenter 逐列中心线,value noise(scale 130、幅度 ±3)确定性缓弯,
相邻列步长 <=1、遇弯补格保证 4 连通;默认图主街仍笔直。
- VillageArt:水田/菜畦/树丛/农舍渲染(复用成熟 sprite 与同一立面纯函数)、农舍门窗计入夜光、
新增 drawMapRegion 局部真实离屏渲染。
- Game:P30 证据钩子 LV_MAPGEN_P30_SHOT=1(整图 3072x2304 day/night + 田块/主路 512x256@4px)。
- 回归 +5:组团规模/空区填充/田块合规/农舍可达确定性/主路确定性弯曲。
Kernel 92 / Desktop 156 全绿;Release 0 警告 0 错误;
final_digest=953775FAEB2F… 3 次一致、performance_determinism=PASS;
64x48=6042052、256x192=1284656962 锁定不变。
Diffstat (limited to 'src/LivingVillage.Desktop/VillageArt.fs')
| -rw-r--r-- | src/LivingVillage.Desktop/VillageArt.fs | 59 |
1 files changed, 57 insertions, 2 deletions
diff --git a/src/LivingVillage.Desktop/VillageArt.fs b/src/LivingVillage.Desktop/VillageArt.fs index 3e52546..4faa886 100644 --- a/src/LivingVillage.Desktop/VillageArt.fs +++ b/src/LivingVillage.Desktop/VillageArt.fs @@ -656,7 +656,7 @@ module VillageArt = spriteBatch.Draw(textures.TileAtlas, XnaRectangle(tileX x, tileY y, cell, cell), tileSourceRectangle sprite, XnaColor.White) 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 + let drawHouse (building: MapGen.Building) = let left = building.Left let right = building.Left + building.Width - 1 match houseFacadeVariant building with @@ -690,6 +690,11 @@ module VillageArt = let wallSprite = if x = building.DoorX then CourtyardDoorSprite else WallLatticeSprite drawCell wallSprite x building.DoorY + for building in map.Buildings do + drawHouse building + // P30 散落农舍与沿河民居共用同一套立面纯函数。 + for farmhouse in map.Farmhouses do + drawHouse farmhouse // P26 河岸装饰:护岸石垒 / 芦苇 / 垂柳(垂柳占上下两格),只在大图生成。 for decoration in map.Decorations do match decoration.Kind with @@ -698,6 +703,11 @@ module VillageArt = | MapGen.RiverDecorationKind.Willow -> drawCell WillowTopSprite decoration.X decoration.Y drawCell WillowBaseSprite decoration.X (decoration.Y + 1) + // P30 乡村树丛:竹丛 / 灌木丛(纯视觉,不写瓦片、不影响通行)。 + for grove in map.Groves do + match grove.Kind with + | MapGen.BambooClump -> drawCell BambooSprite grove.X grove.Y + | MapGen.ShrubClump -> drawCell ShrubSprite grove.X grove.Y /// 桥头灯笼瓦片:每座桥每列的最上/最下一格(桥两端),用于挂灯笼与夜间暖光。 let bridgeLanternTiles (map: MapGen.Result) : (int * int) list = @@ -710,10 +720,11 @@ module VillageArt = /// P29 夜景灯光源瓦片:桥头灯笼 + 民居门窗暖光(确定性纯函数,便于单测)。 /// 每户至少门格发光;变体 A 再取第一扇横向窗,变体 B(整面格栅窗)与门同格故不另加。 + /// P30:散落农舍的门窗暖光一并计入。 let nightLightTiles (map: MapGen.Result) : (int * int) list = let lanterns = bridgeLanternTiles map let houseLights = - map.Buildings + (map.Buildings @ map.Farmhouses) |> List.collect (fun building -> let windowTiles = if houseFacadeVariant building = 0 then @@ -772,6 +783,9 @@ module VillageArt = match code with | 1 -> draw position (waterSpriteAt position) | 2 -> draw position StonePathSprite + // P30 乡村空区:水田(4)走静态水面素材、菜畦(5)走菜地素材;均为成熟 tile。 + | 4 -> draw position WaterSprite + | 5 -> draw position GardenSprite | _ -> draw position GrassSprite let drawBaseTile (position: TilePosition) = @@ -907,6 +921,9 @@ module VillageArt = match code with | 1 -> WaterSprite | 2 -> StonePathSprite + // P30 乡村空区:水田走静态水面、菜畦走菜地素材。 + | 4 -> WaterSprite + | 5 -> GardenSprite | _ -> GrassSprite for y in 0 .. map.Height - 1 do for x in 0 .. map.Width - 1 do @@ -942,6 +959,8 @@ module VillageArt = | 1 -> WaterSpriteB | _ -> WaterSpriteC | 2 -> StonePathSprite + | 4 -> WaterSprite + | 5 -> GardenSprite | _ -> GrassSprite let mutable drawn = 0 for y in y0 .. y1 do @@ -954,6 +973,42 @@ module VillageArt = drawNightGlows spriteBatch pixel map (4 * Sim.tilePixels) (int (150.0f * glowScale)) tileX tileY Sim.tilePixels drawn + /// P30 证据用:把地图的任意 tile 矩形 [tileX0,tileY0,tilesW,tilesH] 以 cell px/tile 真实 + /// 离屏渲染到 target(含民居/田块/树丛/桥/河岸装饰与可选夜光),返回绘制瓦片数。 + /// 与 drawMapFitted/drawMapViewport 共用 drawMapStructures / drawNightGlows 纯函数。 + let drawMapRegion + (spriteBatch: SpriteBatch) + (textures: ArtTextures) + (pixel: Texture2D) + (tileX0: int) + (tileY0: int) + (tilesW: int) + (tilesH: int) + (cell: int) + (map: MapGen.Result) + (tint: XnaColor) + (glowScale: float32) : int = + let tileX x = (x - tileX0) * cell + let tileY y = (y - tileY0) * cell + let spriteOf code = + match code with + | 1 -> WaterSprite + | 2 -> StonePathSprite + | 4 -> WaterSprite + | 5 -> GardenSprite + | _ -> GrassSprite + let mutable drawn = 0 + for y in tileY0 .. tileY0 + tilesH - 1 do + for x in tileX0 .. tileX0 + tilesW - 1 do + if x >= 0 && x < map.Width && y >= 0 && y < map.Height then + let code = map.Tiles.[y * map.Width + x] + spriteBatch.Draw(textures.TileAtlas, XnaRectangle(tileX x, tileY y, cell, cell), tileSourceRectangle (spriteOf code), tint) + drawn <- drawn + 1 + drawMapStructures spriteBatch textures pixel tileX tileY cell map + if glowScale > 0.0f then + drawNightGlows spriteBatch pixel map (4 * cell) (int (150.0f * glowScale)) tileX tileY cell + drawn + let drawCharacter (spriteBatch: SpriteBatch) (textures: ArtTextures) |
