summaryrefslogtreecommitdiff
path: root/src/LivingVillage.Desktop.Tests/P74LaunchTransitionTests.fs
blob: 880f33bd3ee45d5a05748cd408e302fb5270d02a (plain)
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
namespace LivingVillage.Desktop.Tests

open Microsoft.VisualStudio.TestTools.UnitTesting
open LivingVillage.Desktop
open LivingVillage.Kernel
open LivingVillage.Kernel.Sim

/// P74 回归:启动开场过渡(水墨渐显)纯函数性质 + 开始界面布局入口。
[<TestClass>]
type P74LaunchTransitionTests () =

    let width = 1280
    let height = 720

    [<TestMethod>]
    member _.InkRevealDissolvesMonotonicallyAndStaysSoft () =
        // 起手满墨、96 帧后散尽,且整体强度随帧非增(确定性 ease-out)。
        Assert.AreEqual<float32>(1.0f, InkReveal.inkStrength 0L)
        Assert.AreEqual<float32>(0.0f, InkReveal.inkStrength InkReveal.dissolveFrames)
        Assert.AreEqual<float32>(0.0f, InkReveal.inkStrength 140L)
        let strengths = [ 0L; 8L; 30L; 60L; 95L ] |> List.map InkReveal.inkStrength
        Assert.AreEqual<float32 list>(strengths, strengths |> List.sortDescending)
        // 墨滴始终存在、均在画布内、alpha < 255(柔和墨晕,非实心黑块)、半径不覆盖半屏。
        for frame in [ 0L; 8L; 30L; 60L; 95L ] do
            let dabs = InkReveal.dabs frame width height
            Assert.IsTrue(dabs.Length > 0, "墨滴集合不得为空")
            for dab in dabs do
                Assert.IsTrue(dab.Alpha >= 0 && dab.Alpha < 255, sprintf "alpha %d 越界" dab.Alpha)
                Assert.IsTrue(dab.Rx > 0 && dab.Rx < width / 2, "Rx 覆盖过半屏")
                Assert.IsTrue(dab.Ry > 0 && dab.Ry < height / 2, "Ry 覆盖过半屏")

    [<TestMethod>]
    member _.InkRevealDabsChangeOverTheTransition () =
        // 同一帧两次调用一致(确定性);不同帧墨滴布局不同(动画在变)。
        Assert.AreEqual<InkReveal.Dab list>(InkReveal.dabs 20L width height, InkReveal.dabs 20L width height)
        Assert.AreNotEqual<InkReveal.Dab list>(InkReveal.dabs 8L width height, InkReveal.dabs 60L width height)

    [<TestMethod>]
    member _.LaunchScreenTransitionIsDeterministic () =
        Assert.AreEqual<float32>(0.0f, LaunchScreen.revealProgress 0L)
        Assert.AreEqual<float32>(1.0f, LaunchScreen.revealProgress LaunchScreen.fadeInFrames)
        Assert.AreEqual<float32>(1.0f, LaunchScreen.veilAlpha 0L)
        Assert.AreEqual<float32>(0.0f, LaunchScreen.veilAlpha LaunchScreen.durationFrames)
        Assert.IsTrue(LaunchScreen.isComplete LaunchScreen.durationFrames)
        Assert.IsFalse(LaunchScreen.isComplete (LaunchScreen.durationFrames - 1L))
        Assert.AreEqual<string>("江南水乡", LaunchScreen.title)

    [<TestMethod>]
    member _.StartMenuLayoutExposesStartLoadExit () =
        // 开场结束后的可交互开始界面:无存档 → 开始/读档/退出。
        let fresh = MenuState.create { Paused = false; Speed = OneX } false
        Assert.AreEqual<MenuPage>(MainMenu, fresh.Page)
        Assert.AreEqual<MenuItem list>([ NewGameItem; LoadItem; ExitItem ], MenuState.items fresh)
        let labels = MenuState.items fresh |> List.map MenuState.itemLabel
        Assert.AreEqual<string list>([ "开始"; "读档"; "退出" ], labels)
        // 有进行中的世界 → 继续/读档/退出。
        let resumed = MenuState.create { Paused = false; Speed = OneX } true
        Assert.AreEqual<MenuItem list>([ ContinueItem; LoadItem; ExitItem ], MenuState.items resumed)
        Assert.AreEqual<string>("继续", MenuState.itemLabel (MenuState.selectedItem resumed))