diff options
| author | Somhairle H. Marisol <[email protected]> | 2026-09-28 20:26:42 +0800 |
|---|---|---|
| committer | Somhairle H. Marisol <[email protected]> | 2026-09-28 20:26:42 +0800 |
| commit | 08925d4863d8aaf93a974b8fa21a91e931a0928e (patch) | |
| tree | f18055c232fc1a6022eeab552402185c6948ec02 /src/LivingVillage.Desktop/FloaterArt.fs | |
| parent | 2ab4b8a22aaec3482d62433cfa4b73a657f2a165 (diff) | |
| download | living-village-08925d4863d8aaf93a974b8fa21a91e931a0928e.tar.gz | |
p47: 场景细节升级 — 河道倒影(waterFrameTickAt微抖)+岸边芦苇加密度+鸭/叶漂浮元素+近景屋顶统一光源阴影
Diffstat (limited to 'src/LivingVillage.Desktop/FloaterArt.fs')
| -rw-r--r-- | src/LivingVillage.Desktop/FloaterArt.fs | 103 |
1 files changed, 103 insertions, 0 deletions
diff --git a/src/LivingVillage.Desktop/FloaterArt.fs b/src/LivingVillage.Desktop/FloaterArt.fs new file mode 100644 index 0000000..53a0793 --- /dev/null +++ b/src/LivingVillage.Desktop/FloaterArt.fs @@ -0,0 +1,103 @@ +namespace LivingVillage.Desktop + +/// P47 漂浮小元素(鸭子浮标 / 漂浮落叶)原创点阵图集生成器。 +/// 复用 P45 `CharacterArt` 的点阵像素代码管线:把 12x8 的字符画按 2x 放大成 24x16 的 +/// 单元,4 格一横排(鸭 A/B、叶 A/B)。全部为原创像素画,不采样任何外部素材, +/// 也不使用程序几何矩形冒充成品。 +module FloaterArt = + + let sourceWidth = 12 + let sourceHeight = 8 + let scale = 2 + let cellWidth = sourceWidth * scale // 24 + let cellHeight = sourceHeight * scale // 16 + let frameCount = 2 + let kindCount = 2 + let atlasWidth = cellWidth * frameCount * kindCount // 96 + let atlasHeight = cellHeight // 16 + + let duckIndex = 0 + let leafIndex = 1 + + let private duckFrameA = + [ "............" + "....2222...." + "....2422...." + "...32222...." + "..1111111..." + ".111111111.." + ".111111111.." + "..5555555..." ] + + let private duckFrameB = + [ "............" + ".....2222..." + ".....2422..." + "....32222..." + "..1111111..." + ".111111111.." + ".111111111.." + "..5555555..." ] + + let private leafFrameA = + [ "............" + ".....6......" + "....676....." + "...67776...." + "..6777776..." + "...67776...." + "....676....." + ".....6......" ] + + let private leafFrameB = + [ "............" + ".....6......" + "....676....." + "...67776...." + "..6776776..." + "...67776...." + "....676....." + ".....6......" ] + + let private colorOf (ch: char) : (int * int * int) option = + match ch with + | '1' -> Some(236, 228, 206) // 鸭身奶白 + | '2' -> Some(248, 242, 228) // 鸭头高光 + | '3' -> Some(232, 150, 60) // 鸭喙橙 + | '4' -> Some(40, 42, 54) // 鸭眼深色 + | '5' -> Some(70, 100, 120) // 水面暗线 + | '6' -> Some(96, 120, 64) // 叶缘深绿 + | '7' -> Some(150, 172, 96) // 叶身浅绿 + | _ -> None + + /// 单元索引:kind 0=鸭 1=叶,frame 0/1。 + let cellIndex (kind: int) (frame: int) : int = + (kind % kindCount) * frameCount + (frame % frameCount) + + let sourceRectangle (kind: int) (frame: int) : Microsoft.Xna.Framework.Rectangle = + Microsoft.Xna.Framework.Rectangle(cellIndex kind frame * cellWidth, 0, cellWidth, cellHeight) + + let buildAtlas (device: Microsoft.Xna.Framework.Graphics.GraphicsDevice) : Microsoft.Xna.Framework.Graphics.Texture2D = + let data = Array.zeroCreate<Microsoft.Xna.Framework.Color> (atlasWidth * atlasHeight) + let put (index: int) (rows: string list) = + rows + |> List.iteri (fun rowIndex row -> + row + |> Seq.iteri (fun columnIndex ch -> + match colorOf ch with + | None -> () + | Some(r, g, b) -> + let px = index * cellWidth + columnIndex * scale + for dy in 0 .. scale - 1 do + for dx in 0 .. scale - 1 do + let tx = px + dx + let ty = rowIndex * scale + dy + if tx >= 0 && tx < atlasWidth && ty >= 0 && ty < atlasHeight then + data.[ty * atlasWidth + tx] <- Microsoft.Xna.Framework.Color(r, g, b))) + put (cellIndex duckIndex 0) duckFrameA + put (cellIndex duckIndex 1) duckFrameB + put (cellIndex leafIndex 0) leafFrameA + put (cellIndex leafIndex 1) leafFrameB + let texture = new Microsoft.Xna.Framework.Graphics.Texture2D(device, atlasWidth, atlasHeight) + texture.SetData data + texture |
