summaryrefslogtreecommitdiff
path: root/src/LivingVillage.Desktop.Tests
diff options
context:
space:
mode:
authorSomhairle H. Marisol <[email protected]>2026-09-21 11:41:17 +0800
committerSomhairle H. Marisol <[email protected]>2026-09-21 11:41:17 +0800
commit89be1bce62a01c6994c0de4d5c9f05338f3b4d4f (patch)
treeebba12c078880ae4017318d0c36fc12708221791 /src/LivingVillage.Desktop.Tests
parent7f0c40dc89672d218f10ba3f81a0ee235da30969 (diff)
downloadliving-village-89be1bce62a01c6994c0de4d5c9f05338f3b4d4f.tar.gz
feat(desktop): 江南氛围标题画面
新增 TitleScreen 纯布局模块(确定性、可测):五段暮色渐变天幕、黛瓦屋脊/檐口轮廓带(复用图集 8/9 号地块)、水面倒影带(1 号地块)、岸边灯笼光晕、江南水乡四倍大字标题;主菜单改为纵向简洁排布浮于其上,子页面板按内容自适应高度,去除全屏暗色遮罩大黑块。Xvfb 截图像素自查通过。
Diffstat (limited to 'src/LivingVillage.Desktop.Tests')
-rw-r--r--src/LivingVillage.Desktop.Tests/PrototypeTests.fs39
1 files changed, 39 insertions, 0 deletions
diff --git a/src/LivingVillage.Desktop.Tests/PrototypeTests.fs b/src/LivingVillage.Desktop.Tests/PrototypeTests.fs
index 3e15272..ab7ae1a 100644
--- a/src/LivingVillage.Desktop.Tests/PrototypeTests.fs
+++ b/src/LivingVillage.Desktop.Tests/PrototypeTests.fs
@@ -203,6 +203,45 @@ type PrototypeTests () =
Assert.IsTrue(first.Tiles |> List.exists (fun tile -> tile.Kind = (VillageArt.StonePaving)))
[<TestMethod>]
+ member _.TitleScreenLayoutIsDeterministicAndLayered () =
+ let first = TitleScreen.layout 1280 720
+ let second = TitleScreen.layout 1280 720
+ Assert.AreEqual<TitleScreen.TitleLayout>(first, second)
+
+ // Title: existing CJK atlas text, large scale, centered headline.
+ Assert.AreEqual<string>("江南水乡", first.TitleText)
+ Assert.AreEqual<int>(4, first.TitleScale)
+
+ // Background must be a layered gradient, never a flat fullscreen block.
+ Assert.IsTrue(first.SkyBands.Length >= 4)
+ Assert.AreEqual<int>(first.SkyBands.Length, first.SkyBands |> List.distinct |> List.length)
+
+ // Skyline reuses the Jiangnan roof tiles (ridge=8, eave=9) across the full width.
+ let roofSlots = TitleScreen.roofSlots
+ Assert.AreEqual<int>(8, fst roofSlots)
+ Assert.AreEqual<int>(9, snd roofSlots)
+ Assert.AreEqual<int>(1280 / 32, first.RoofTileSlots.Length)
+ Assert.IsTrue(first.RoofTileSlots |> List.forall (fun slot -> slot = 8 || slot = 9))
+ Assert.IsTrue(first.RoofTileSlots |> List.contains 8)
+ Assert.IsTrue(first.RoofTileSlots |> List.contains 9)
+
+ // Water band reuses the water tile slot and anchors the lantern row.
+ Assert.AreEqual<int>(1, TitleScreen.waterSlot)
+ Assert.AreEqual<int>(2, first.WaterRows.Length)
+ Assert.IsTrue(first.Lanterns.Length >= 3)
+ let lanternColor, lanternHalo = TitleScreen.lanternColors
+ Assert.AreEqual<int>(212, lanternColor.R)
+ Assert.AreEqual<int>(92, lanternColor.G)
+ Assert.AreEqual<int>(74, lanternColor.B)
+ Assert.IsTrue(lanternHalo.R > lanternColor.R && lanternHalo.G > lanternColor.G)
+
+ // Menu items form one vertical column below the title.
+ Assert.IsTrue(first.MenuTopY > first.TitleY)
+ Assert.IsTrue(first.MenuLineHeight > 0)
+ Assert.IsTrue(first.PanelX + first.PanelWidth <= 1280)
+ Assert.IsTrue(first.PanelY + first.PanelHeight <= 720)
+
+ [<TestMethod>]
member _.NpcVariantsAreStableAndAnimationCoversFourDirectionsAndTwoFrames () =
let sameNpc = npcVisualVariant (NpcId 7)
let repeatedNpc = npcVisualVariant (NpcId 7)