diff options
| author | Somhairle H. Marisol <[email protected]> | 2026-09-22 03:13:42 +0800 |
|---|---|---|
| committer | Somhairle H. Marisol <[email protected]> | 2026-09-22 03:13:42 +0800 |
| commit | 2dd5ef0c5489f8fd656888f7d749a541101d5ad1 (patch) | |
| tree | 4adeb67b100fc2bdc3b63d93633161f53b9c1331 /src/LivingVillage.Desktop/VillageArt.fs | |
| parent | d06656aa968ccb2769ba7c90c97f57f2818bb828 (diff) | |
| download | living-village-2dd5ef0c5489f8fd656888f7d749a541101d5ad1.tar.gz | |
feat(mapgen): 默认可玩世界接入生成器 + 河景细节(P20 第三步 B)
- Game:默认 256x192 生成器世界(核心可达区站位),LV_LEGACY_MAP=1 /
LV_MAP_SCALE>1 / LV_MAP_TOUR=1 回退旧路径;StartNewGame 走同一站位。
- VillageArt.drawWorld 新增 pixel 与 mapGen option:Some 时按生成器瓦片绘地面
并叠加桥面/沿河民居/门,跳过 64x48 样例平面与道具;水波沿用 waterFrameTickAt。
- 新增 bridgeLanternTiles;夜间 LanternGlow 沿用既有预乘同心圆(无过曝白芯),
生成器世界用桥头灯笼。
- 新增 LV_RIVERSCAPE_TOUR 真走位巡游与 LV_RECORD_NAME 录屏前缀(证据用)。
Diffstat (limited to 'src/LivingVillage.Desktop/VillageArt.fs')
| -rw-r--r-- | src/LivingVillage.Desktop/VillageArt.fs | 108 |
1 files changed, 67 insertions, 41 deletions
diff --git a/src/LivingVillage.Desktop/VillageArt.fs b/src/LivingVillage.Desktop/VillageArt.fs index 19c9aa6..3ad5b19 100644 --- a/src/LivingVillage.Desktop/VillageArt.fs +++ b/src/LivingVillage.Desktop/VillageArt.fs @@ -600,13 +600,48 @@ module VillageArt = let private offsetTile (position: TilePosition) dx dy : TilePosition = tilePosition (position.X + dx) (position.Y + dy) + 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 bridgeLanternTiles (map: MapGen.Result) : (int * int) list = + map.Bridges + |> List.groupBy fst + |> List.collect (fun (x, entries) -> + let ys = entries |> List.map snd + [ (x, List.min ys); (x, List.max ys) ]) + |> List.distinct + let drawWorld (spriteBatch: SpriteBatch) (textures: ArtTextures) + (pixel: Texture2D) (camera: XnaVector2) (viewportWidth: int) (viewportHeight: int) (plan: JiangnanRenderPlan) + (mapGen: MapGen.Result option) (tick: int64) (tint: XnaColor) = let draw position sprite = @@ -622,26 +657,30 @@ module VillageArt = // Procedural terrain for the 512x384 large world: water/pebble/peat codes map // onto the jiangnan atlas sprites with deterministic ripple continuity. + // 生成器世界:1 水 / 2 石板路 / 3 泥炭 / 0 草地。泥炭按草地渲染,路走石板贴图。 let drawTerrainTile (position: TilePosition) (code: int) = match code with | 1 -> draw position (waterSpriteAt position) | 2 -> draw position StonePathSprite - | 3 -> draw position StonePathSprite | _ -> draw position GrassSprite let drawBaseTile (position: TilePosition) = - match ProceduralMap.terrainOption, ProceduralMap.bigWorldActive with - | (Some terrain, true) -> - let tx, ty = position.X, position.Y - let code = terrain.Tiles.[ty * ProceduralMap.width + tx] - drawTerrainTile position code - | _ -> + match mapGen with + | Some map -> + drawTerrainTile position map.Tiles.[position.Y * map.Width + position.X] + | None -> + match ProceduralMap.terrainOption, ProceduralMap.bigWorldActive with + | (Some terrain, true) -> + let tx, ty = position.X, position.Y + let code = terrain.Tiles.[ty * ProceduralMap.width + tx] + drawTerrainTile position code + | _ -> + match textures.Cc0TileAtlas with + | Some cc0 -> drawCc0Tile spriteBatch cc0 tint (cc0GroundRect position) (position.X * Sim.tilePixels - int camera.X) (position.Y * Sim.tilePixels - int camera.Y) + | None -> draw position GrassSprite match textures.Cc0TileAtlas with | Some cc0 -> drawCc0Tile spriteBatch cc0 tint (cc0GroundRect position) (position.X * Sim.tilePixels - int camera.X) (position.Y * Sim.tilePixels - int camera.Y) | None -> draw position GrassSprite - match textures.Cc0TileAtlas with - | Some cc0 -> drawCc0Tile spriteBatch cc0 tint (cc0GroundRect position) (position.X * Sim.tilePixels - int camera.X) (position.Y * Sim.tilePixels - int camera.Y) - | None -> draw position GrassSprite let tx0, ty0, tx1, ty1 = MapGen.visibleTileRange Sim.mapWidthTiles Sim.mapHeightTiles (int camera.X) (int camera.Y) viewportWidth viewportHeight @@ -649,7 +688,19 @@ module VillageArt = for x in tx0 .. tx1 do drawBaseTile (tilePosition x y) - for localPosition, kind in plan.Grounds do + // 生成器世界:叠加桥面、沿河民居、桥头灯笼;不再绘制 64x48 样例平面与道具。 + match mapGen with + | Some map -> + let mapTileX x = x * Sim.tilePixels - int camera.X + let mapTileY y = y * Sim.tilePixels - int camera.Y + drawMapStructures spriteBatch textures pixel mapTileX mapTileY Sim.tilePixels map + for (lanternX, lanternY) in bridgeLanternTiles map do + draw (tilePosition lanternX lanternY) LanternSprite + | None -> () + + // 回退(64x48 样例世界)或 LV_MAP_SCALE 大世界时仍绘制样例地面/道具。 + let planGrounds = match mapGen with Some _ -> [] | None -> plan.Grounds + for localPosition, kind in planGrounds do let position = worldTile plan localPosition match kind with | Water -> draw position (waterSpriteAt position) @@ -693,7 +744,8 @@ module VillageArt = let drawSingleTile localPosition sprite = draw (worldTile plan localPosition) sprite - for prop in plan.Props do + let planProps = match mapGen with Some _ -> [] | None -> plan.Props + for prop in planProps do match prop.Kind with | House -> drawHouse prop.Position | Bridge -> drawBridge prop.Position @@ -717,37 +769,13 @@ module VillageArt = | 0 -> SmokeSpriteA | 1 -> SmokeSpriteB | _ -> SmokeSpriteC - for prop in plan.Props do + for prop in planProps do match prop.Kind with | House -> draw (offsetTile (worldTile plan prop.Position) 0 -3) smokeSprite | _ -> () /// 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) @@ -767,8 +795,7 @@ module VillageArt = let spriteOf code = match code with | 1 -> WaterSprite - | 2 - | 3 -> StonePathSprite + | 2 -> StonePathSprite | _ -> GrassSprite for y in 0 .. map.Height - 1 do for x in 0 .. map.Width - 1 do @@ -799,8 +826,7 @@ module VillageArt = | 0 -> WaterSprite | 1 -> WaterSpriteB | _ -> WaterSpriteC - | 2 - | 3 -> StonePathSprite + | 2 -> StonePathSprite | _ -> GrassSprite let mutable drawn = 0 for y in y0 .. y1 do |
