From f79839a4bb57b977b7208e5f826a8b0989cbc33e Mon Sep 17 00:00:00 2001 From: "Somhairle H. Marisol" Date: Tue, 22 Sep 2026 00:10:18 +0800 Subject: feat(desktop): P16 HUD 顶部窄信息条(时段/时间/倍速/体力/钱币)+ 冬夜冷色 + 面板/提示渐变重绘 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/LivingVillage.Desktop.Tests/P16UiTests.fs | 59 +++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) (limited to 'src/LivingVillage.Desktop.Tests/P16UiTests.fs') diff --git a/src/LivingVillage.Desktop.Tests/P16UiTests.fs b/src/LivingVillage.Desktop.Tests/P16UiTests.fs index 0bfdb62..0db4506 100644 --- a/src/LivingVillage.Desktop.Tests/P16UiTests.fs +++ b/src/LivingVillage.Desktop.Tests/P16UiTests.fs @@ -64,3 +64,62 @@ type P16StartMenuTests () = Assert.AreEqual([ ContinueItem; LoadItem; ExitItem ], MenuState.items main) Assert.AreEqual([ "继续"; "读档"; "退出" ], MenuState.items main |> List.map MenuState.itemLabel) Assert.AreEqual(ContinueGame, MenuState.update Confirm main |> snd) + +// ---- P16 HUD 顶部窄信息条 ---- + +[] +type P16HudTests () = + + let world = Sim.initialWorldN 42UL 4 + + [] + member _.HudBarIsANarrowStripNotAFullscreenBlock () = + Assert.IsTrue(HudLayout.barHeight <= 40, "HUD bar must stay a narrow strip") + Assert.IsTrue(HudLayout.barHeight * 4 < 720, "HUD bar must not dominate the viewport") + + [] + member _.HudSegmentsAreDeterministicAndUseRealState () = + let control = SimulationControl.initial + let segments = HudLayout.segments world control + Assert.AreEqual([ "时段"; "时间"; "倍速"; "体力"; "钱币" ], segments |> List.map (fun segment -> segment.Label)) + Assert.AreEqual(segments, HudLayout.segments world control) + let energy = segments |> List.find (fun segment -> segment.Label = "体力") + Assert.AreEqual(sprintf "%.0f" world.Avatar.Mind.Needs.Energy, energy.Value) + let money = segments |> List.find (fun segment -> segment.Label = "钱币") + Assert.AreEqual(sprintf "%.0f" world.Avatar.Mind.Needs.Money, money.Value) + + [] + member _.HudLayoutPlacesSegmentsDeterministicallyWithinWidth () = + let placed = HudLayout.layout (HudLayout.segments world SimulationControl.initial) + Assert.AreEqual(5, placed.Length) + let (firstX, _, _) = List.head placed + Assert.AreEqual(HudLayout.paddingX, firstX) + placed + |> List.pairwise + |> List.iter (fun ((x1, w1, _), (x2, _, _)) -> + Assert.IsTrue(x2 >= x1 + w1, sprintf "segments overlap: %d+%d vs %d" x1 w1 x2)) + let (lastX, lastWidth, _) = List.last placed + Assert.IsTrue(lastX + lastWidth <= 1280, "last segment must fit inside a 1280 viewport") + + [] + member _.HudClockAndPeriodArePureFunctions () = + let ticksPerHour = Sim.ticksPerDay / 24L + Assert.AreEqual("12:00", M6Presentation.clockTimeLabel (12L * ticksPerHour)) + Assert.AreEqual("00:00", M6Presentation.clockTimeLabel 0L) + Assert.AreEqual("06:30", M6Presentation.clockTimeLabel (6L * ticksPerHour + ticksPerHour / 2L)) + Assert.AreEqual("白天", M6Presentation.timePeriodLabel (12L * ticksPerHour)) + Assert.AreEqual("夜晚", M6Presentation.timePeriodLabel 0L) + Assert.AreEqual("清晨", M6Presentation.timePeriodLabel (6L * ticksPerHour)) + Assert.AreEqual("黄昏", M6Presentation.timePeriodLabel (19L * ticksPerHour)) + + [] + member _.HudNightPaletteLeansCoolAndLabelsAreAtlasBacked () = + let day = HudLayout.palette Day + let night = HudLayout.palette Night + Assert.IsTrue(night.Accent.B > night.Accent.R, "night accent should lean cool/blue (winter-night tint)") + Assert.IsTrue(day.Accent.R > day.Accent.B, "day accent should lean warm") + for label in [ "时段"; "时间"; "倍速"; "体力"; "钱币" ] do + Assert.IsTrue(PixelText.isRenderable label, sprintf "HUD label %s must render" label) + Assert.IsTrue(ChineseText.requiredUiLabels |> List.contains "时段") + Assert.IsTrue(ChineseText.requiredUiLabels |> List.contains "体力") + Assert.IsTrue(ChineseText.requiredUiLabels |> List.contains "钱币") -- cgit v1.2.3