summaryrefslogtreecommitdiff
path: root/src/LivingVillage.Desktop/TitleScreen.fs
blob: 00cf5b8638c15352cdbb4b54cbdb2639916f4c89 (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
104
105
106
107
108
109
110
111
112
113
114
namespace LivingVillage.Desktop

module TitleScreen =

    type ColorRgb =
        { R: int
          G: int
          B: int }

    type TitleLayout =
        { SkyBands: ColorRgb list
          RoofTileSlots: int list
          RidgeY: int
          EaveY: int
          WaterRows: int list
          Lanterns: (int * int) list
          TitleText: string
          TitleX: int
          TitleY: int
          TitleScale: int
          MenuX: int
          MenuTopY: int
          MenuLineHeight: int
          PanelX: int
          PanelY: int
          PanelWidth: int
          PanelHeight: int
          HeadingY: int
          FirstItemY: int
          CursorX: int
          CursorWidth: int
          TextX: int }

    type TextRect =
        { X: int
          Y: int
          Width: int
          Height: int }

    let rectsDisjoint (a: TextRect) (b: TextRect) : bool =
        a.X + a.Width <= b.X
        || b.X + b.Width <= a.X
        || a.Y + a.Height <= b.Y
        || b.Y + b.Height <= a.Y

    /// Cursor and label rectangles for one menu row. The cursor is drawn in its own
    /// column; the label always starts to the right of it, so they can never overprint.
    let selectionRects (layout: TitleLayout) (rowIndex: int) : TextRect * TextRect =
        let y = layout.FirstItemY + rowIndex * layout.MenuLineHeight
        { X = layout.CursorX; Y = y; Width = layout.CursorWidth; Height = 16 },
        { X = layout.TextX; Y = y; Width = layout.PanelX + layout.PanelWidth - layout.TextX - 24; Height = 16 }

    // Palette mirrors the VillageArt atlas: roof (45,49,57)/(30,33,38), water (54,116,145),
    // lantern paper (212,92,74). Purely decorative reuse of existing art colors.
    let private skyBands : ColorRgb list =
        [ { R = 16; G = 26; B = 42 }
          { R = 20; G = 36; B = 52 }
          { R = 24; G = 46; B = 62 }
          { R = 28; G = 56; B = 68 }
          { R = 32; G = 64; B = 72 } ]

    let private roofRidgeSlot = 8
    let private roofEaveSlot = 9
    let private waterTileSlot = 1
    let private lanternColor = { R = 212; G = 92; B = 74 }
    let private lanternHalo = { R = 252; G = 216; B = 148 }

    let lanternColors : ColorRgb * ColorRgb = lanternColor, lanternHalo
    let skyBandCount = skyBands.Length
    let waterSlot = waterTileSlot
    let roofSlots = roofRidgeSlot, roofEaveSlot

    let layout (viewportWidth: int) (viewportHeight: int) : TitleLayout =
        let width = max 320 viewportWidth
        let height = max 240 viewportHeight
        let tilePixels = 32
        let columns = width / tilePixels
        let roofTileSlots =
            [ 0 .. columns - 1 ]
            |> List.map (fun column ->
                if column % 4 = 0 || column % 7 = 3 then roofRidgeSlot else roofEaveSlot)
        let waterRows =
            [ height - 96
              height - 64 ]
        let lanternCount = max 3 (columns / 10)
        let lanterns =
            [ 1 .. lanternCount ]
            |> List.map (fun index ->
                let x = index * width / (lanternCount + 1)
                let y = (List.head waterRows) - 44 + (if index % 2 = 0 then 12 else 0)
                x, y)
        let panelWidth = min 460 (width - 64)
        { SkyBands = skyBands
          RoofTileSlots = roofTileSlots
          RidgeY = 44
          EaveY = 76
          WaterRows = waterRows
          Lanterns = lanterns
          TitleText = "江南水乡"
          TitleX = (width - 4 * (4 * 16)) / 2
          TitleY = 120
          TitleScale = 4
          MenuX = (width - panelWidth) / 2 + 40
          MenuTopY = height / 2 - 40
          MenuLineHeight = 30
          PanelX = (width - panelWidth) / 2
          PanelY = height / 2 - 64
          PanelWidth = panelWidth
          PanelHeight = min 360 (height - height / 2 - 40)
          HeadingY = height / 2 - 64 + 20
          FirstItemY = height / 2 - 64 + 60
          CursorX = (width - panelWidth) / 2 + 24
          CursorWidth = 20
          TextX = (width - panelWidth) / 2 + 24 + 20 + 12 }