namespace LivingVillage.Desktop open System open Microsoft.Xna.Framework open Microsoft.Xna.Framework.Graphics open LivingVillage.Kernel /// P47 场景细节渲染层:把 `SceneDetail` 的纯函数结果落成画面。 /// 反射用「光源精灵垂直镜像 + 相位微抖」,岸边芦苇/漂浮元素用既有瓦片精灵与原创点阵图集, /// 近景屋顶用既有屋瓦精灵 + 统一方向阴影。全部只读,不改瓦片/可达性。 module SceneDetailRender = let private tileX (camera: Vector2) (x: int) = x * Sim.tilePixels - int camera.X let private tileY (camera: Vector2) (y: int) = y * Sim.tilePixels - int camera.Y let private drawFlipVertical (spriteBatch: SpriteBatch) (atlas: Texture2D) (source: Rectangle) (x: int) (y: int) (color: Color) = spriteBatch.Draw( atlas, Rectangle(x, y, Sim.tilePixels, Sim.tilePixels), Nullable(source), color, 0.0f, Vector2.Zero, SpriteEffects.FlipVertically, 0.0f) /// 河道倒影:岸上每个光源在其正下方水面格画一份垂直镜像,随 waterFrameTickAt 相位水平微抖。 let private drawReflections (spriteBatch: SpriteBatch) (textures: VillageArt.ArtTextures) (camera: Vector2) (map: MapGen.Result) (tick: int64) = let source, atlas = match textures.Cc0TileAtlas with | Some cc0 -> VillageArt.cc0TileRect VillageArt.cc0TileIndexStoneLantern, cc0 | None -> VillageArt.atlasTileRectangle 20, textures.TileAtlas for (x, y, alpha) in SceneDetail.reflectionStreaks map do let wobble = SceneDetail.reflectionWobbleAt tick x y let color = VillageArt.premultiply 255 214 168 alpha drawFlipVertical spriteBatch atlas source (tileX camera x + wobble) (tileY camera y) color /// 岸边芦苇加密度:用既有芦苇精灵补绘一层贴水芦苇。 let private drawBankReeds (spriteBatch: SpriteBatch) (textures: VillageArt.ArtTextures) (camera: Vector2) (map: MapGen.Result) = match textures.Cc0TileAtlas with | Some cc0 -> for (x, y) in SceneDetail.bankReedTiles map do spriteBatch.Draw(cc0, Rectangle(tileX camera x, tileY camera y, Sim.tilePixels, Sim.tilePixels), Nullable(VillageArt.cc0TileRect VillageArt.cc0TileIndexReeds), Color.White) | None -> let source = VillageArt.atlasTileRectangle 18 for (x, y) in SceneDetail.bankReedTiles map do spriteBatch.Draw(textures.TileAtlas, Rectangle(tileX camera x, tileY camera y, Sim.tilePixels, Sim.tilePixels), Nullable(source), Color.White) /// 漂浮元素:原创点阵鸭/叶,按 tick 慢漂移。 let private drawFloaters (spriteBatch: SpriteBatch) (textures: VillageArt.ArtTextures) (camera: Vector2) (map: MapGen.Result) (tick: int64) = for (x, y, kind) in SceneDetail.floatingProps map do let seed = x * 31 + y * 7 let dx, dy = SceneDetail.floatDrift tick seed let frame = SceneDetail.floatFrame tick seed let kindIndex = match kind with | SceneDetail.DuckFloat -> FloaterArt.duckIndex | SceneDetail.FallenLeaf -> FloaterArt.leafIndex let source = FloaterArt.sourceRectangle kindIndex frame spriteBatch.Draw( textures.FloaterAtlas, Rectangle(tileX camera x + dx + (Sim.tilePixels - FloaterArt.cellWidth) / 2, tileY camera y + dy + (Sim.tilePixels - FloaterArt.cellHeight) / 2, FloaterArt.cellWidth, FloaterArt.cellHeight), Nullable(source), Color.White) /// 近景楼层层错落:屏幕空间前景屋顶带,所有阴影统一投向右下(SceneDetail.shadowOffsetPx)。 let private drawForeground (spriteBatch: SpriteBatch) (textures: VillageArt.ArtTextures) (viewportWidth: int) (viewportHeight: int) (tick: int64) = let ridgeSource = VillageArt.atlasTileRectangle 8 let eaveSource = VillageArt.atlasTileRectangle 9 let shadowColor = VillageArt.premultiply 8 12 18 120 let dx, dy = SceneDetail.shadowOffsetPx for (x, y, w) in SceneDetail.foregroundRooftops viewportWidth viewportHeight tick do // 统一方向阴影:先把 eave 的暗色镜像平移一份到右下,再画本体。 spriteBatch.Draw(textures.TileAtlas, Rectangle(x + dx, y + dy, w, Sim.tilePixels), Nullable(eaveSource), shadowColor) spriteBatch.Draw(textures.TileAtlas, Rectangle(x, y - Sim.tilePixels, w, Sim.tilePixels), Nullable(ridgeSource), Color.White) spriteBatch.Draw(textures.TileAtlas, Rectangle(x, y, w, Sim.tilePixels), Nullable(eaveSource), Color.White) /// 一次性绘制全部 P47 场景细节(倒影 → 岸边芦苇 → 漂浮元素 → 近景前景层)。 let draw (spriteBatch: SpriteBatch) (textures: VillageArt.ArtTextures) (pixel: Texture2D) (camera: Vector2) (viewportWidth: int) (viewportHeight: int) (map: MapGen.Result) (tick: int64) = drawReflections spriteBatch textures camera map tick drawBankReeds spriteBatch textures camera map drawFloaters spriteBatch textures camera map tick drawForeground spriteBatch textures viewportWidth viewportHeight tick