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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
|
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
ControlsPanelY: int
ControlsRowHeight: int
ControlsKeyX: int
ControlsKeyWidth: int
ControlsActionX: 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
/// Key-name and action rectangles for one controls-page row. The key column has a
/// fixed width shared by every row, so all action texts start on the same x.
let controlRowRects (layout: TitleLayout) (rowIndex: int) : TextRect * TextRect =
let y = layout.ControlsPanelY + 60 + rowIndex * layout.ControlsRowHeight
{ X = layout.ControlsKeyX; Y = y; Width = layout.ControlsKeyWidth; Height = 16 },
{ X = layout.ControlsActionX; Y = y; Width = layout.PanelX + layout.PanelWidth - layout.ControlsActionX - 24; Height = 16 }
/// 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
ControlsPanelY = max 16 (height - 480)
ControlsRowHeight = 25
ControlsKeyX = (width - panelWidth) / 2 + 24
ControlsKeyWidth = 120
ControlsActionX = (width - panelWidth) / 2 + 24 + 120 + 12 }
|