diff options
Diffstat (limited to 'src/LivingVillage.Desktop/HudLayout.fs')
| -rw-r--r-- | src/LivingVillage.Desktop/HudLayout.fs | 68 |
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) } |
