summaryrefslogtreecommitdiff
path: root/src/LivingVillage.Desktop/FloaterArt.fs
blob: 53a0793ab7e917c789b9e1e3362080a1d0b3eda5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
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