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 (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