summaryrefslogtreecommitdiff
path: root/src/LivingVillage.Desktop/HudLayout.fs
diff options
context:
space:
mode:
authorSomhairle H. Marisol <[email protected]>2026-09-22 00:10:18 +0800
committerSomhairle H. Marisol <[email protected]>2026-09-22 00:10:18 +0800
commitf79839a4bb57b977b7208e5f826a8b0989cbc33e (patch)
treecf0c105b114102bfbb73b3c8d400e83614b861be /src/LivingVillage.Desktop/HudLayout.fs
parentd85cce460fd7fbb8854fb11ba547be1baf576de7 (diff)
downloadliving-village-f79839a4bb57b977b7208e5f826a8b0989cbc33e.tar.gz
feat(desktop): P16 HUD 顶部窄信息条(时段/时间/倍速/体力/钱币)+ 冬夜冷色 + 面板/提示渐变重绘
Diffstat (limited to 'src/LivingVillage.Desktop/HudLayout.fs')
-rw-r--r--src/LivingVillage.Desktop/HudLayout.fs68
1 files changed, 68 insertions, 0 deletions
diff --git a/src/LivingVillage.Desktop/HudLayout.fs b/src/LivingVillage.Desktop/HudLayout.fs
new file mode 100644
index 0000000..d943cec
--- /dev/null
+++ b/src/LivingVillage.Desktop/HudLayout.fs
@@ -0,0 +1,68 @@
+namespace LivingVillage.Desktop
+
+open Microsoft.Xna.Framework
+open LivingVillage.Kernel
+open LivingVillage.Kernel.Sim
+
+/// 顶部窄信息条 HUD 的纯布局/配色模型:只做确定性计算,实际绘制在 Game.fs。
+/// 常驻状态(时段/时间/倍速/体力/钱币)压进一条窄带,绝不用整屏纯色或大黑块。
+module HudLayout =
+
+ let barHeight = 36
+ let accentHeight = 3
+ let paddingX = 16
+ let segmentGap = 20
+ let textScale = 2
+
+ type Segment =
+ { Label: string
+ Value: string }
+
+ let segmentText (segment: Segment) : string = sprintf "%s %s" segment.Label segment.Value
+
+ /// 常驻状态片段,数值全部取自世界真实状态,绝不编造。
+ let segments (world: World) (control: SimulationControl) : Segment list =
+ let needs = world.Avatar.Mind.Needs
+ [ { Label = "时段"; Value = M6Presentation.timePeriodLabel world.Tick }
+ { Label = "时间"; Value = M6Presentation.clockTimeLabel world.Tick }
+ { Label = "倍速"; Value = M6Presentation.speedLabel control }
+ { Label = "体力"; Value = sprintf "%.0f" needs.Energy }
+ { Label = "钱币"; Value = sprintf "%.0f" needs.Money } ]
+
+ /// 段文本(含标签)的像素宽度。
+ let segmentWidth (segment: Segment) : int =
+ FloatingPrompt.measureWidth (segmentText segment) textScale
+
+ /// 左对齐排布,返回 (起点 x, 宽度, 分段);纯函数,便于布局回归断言。
+ let layout (segments: Segment list) : (int * int * Segment) list =
+ let _, placed =
+ segments
+ |> List.fold
+ (fun (x, acc) segment ->
+ let width = segmentWidth segment
+ x + width + segmentGap, (x, width, segment) :: acc)
+ (paddingX, [])
+ List.rev placed
+
+ type Palette =
+ { BarTop: Color
+ BarBottom: Color
+ Accent: Color
+ Label: Color
+ Value: Color }
+
+ /// 白天暖色 / 夜晚(冬夜)冷色微调;均为半透明渐变窄条,无大黑块。
+ let palette (mode: M6DayNight) : Palette =
+ match mode with
+ | Day ->
+ { BarTop = Color(40, 56, 62, 200)
+ BarBottom = Color(22, 34, 40, 200)
+ Accent = Color(212, 168, 96)
+ Label = Color(206, 220, 208)
+ Value = Color(242, 248, 234) }
+ | Night ->
+ { BarTop = Color(22, 30, 48, 205)
+ BarBottom = Color(13, 19, 33, 205)
+ Accent = Color(120, 168, 196)
+ Label = Color(176, 196, 214)
+ Value = Color(228, 238, 246) }