From a5c3400412fbab11d4f4b83a5d0294292eee5f08 Mon Sep 17 00:00:00 2001 From: "Somhairle H. Marisol" Date: Tue, 22 Sep 2026 00:42:44 +0800 Subject: feat(desktop): P17 村民走路节奏差异化(农夫/货郎/书生 纯 tick 节奏) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/LivingVillage.Desktop.Tests/PrototypeTests.fs | 34 +++++++++++++++++++++-- 1 file changed, 31 insertions(+), 3 deletions(-) (limited to 'src/LivingVillage.Desktop.Tests') diff --git a/src/LivingVillage.Desktop.Tests/PrototypeTests.fs b/src/LivingVillage.Desktop.Tests/PrototypeTests.fs index 25f4d02..b8f23a0 100644 --- a/src/LivingVillage.Desktop.Tests/PrototypeTests.fs +++ b/src/LivingVillage.Desktop.Tests/PrototypeTests.fs @@ -335,7 +335,7 @@ type PrototypeTests () = SouthFacing WestFacing EastFacing ] - let sprites = directions |> List.map (fun direction -> npcSpriteSpec (NpcId 7) direction true 4L) + let sprites = directions |> List.map (fun direction -> npcSpriteSpec (NpcId 0) direction true 4L) Assert.AreEqual(sameNpc, repeatedNpc) Assert.AreNotEqual(sameNpc, otherNpc) @@ -533,6 +533,34 @@ type PrototypeTests () = Assert.AreEqual(WalkFrame FrameTwo, VillageArt.characterFrame true 4L) Assert.AreEqual(VillageArt.characterFrame true 12L, VillageArt.characterFrame true 12L) + [] + member _.NpcTradesAndWalkRhythmsAreDistinctAndDeterministic () = + // Three trades repeat by id and stay stable, with no randomness. + Assert.AreEqual(VillageArt.Farmer, VillageArt.npcTrade (NpcId 0)) + Assert.AreEqual(VillageArt.Peddler, VillageArt.npcTrade (NpcId 1)) + Assert.AreEqual(VillageArt.Scholar, VillageArt.npcTrade (NpcId 2)) + Assert.AreEqual(VillageArt.npcTrade (NpcId 9), VillageArt.npcTrade (NpcId 0)) + + // Distinct cadences: peddler shuffles fastest, scholar strolls slowest. + let farmer = VillageArt.rhythmFor VillageArt.Farmer + let peddler = VillageArt.rhythmFor VillageArt.Peddler + let scholar = VillageArt.rhythmFor VillageArt.Scholar + Assert.IsTrue(peddler.WalkWindow < farmer.WalkWindow && farmer.WalkWindow < scholar.WalkWindow) + Assert.IsTrue(peddler.IdleWindow < farmer.IdleWindow && farmer.IdleWindow < scholar.IdleWindow) + + // Same tick, three trade-specific frames (at 12 ticks: Farmer IV, Peddler II, Scholar I). + let frameAt trade tick = VillageArt.animationFrameFor (VillageArt.rhythmFor trade) tick + let frames = + [ VillageArt.Farmer; VillageArt.Peddler; VillageArt.Scholar ] + |> List.map (fun trade -> frameAt trade 12L) + Assert.AreEqual([ FrameFour; FrameTwo; FrameOne ], frames) + Assert.AreEqual(VillageArt.rhythmFor VillageArt.Scholar, VillageArt.rhythmFor VillageArt.Scholar) + + // npcSpriteSpec now follows the NPC's own trade cadence. + Assert.AreEqual(WalkFrame FrameFour, (VillageArt.npcSpriteSpec (NpcId 0) VillageArt.SouthFacing true 12L).Frame) + Assert.AreEqual(WalkFrame FrameTwo, (VillageArt.npcSpriteSpec (NpcId 1) VillageArt.SouthFacing true 12L).Frame) + Assert.AreEqual(WalkFrame FrameOne, (VillageArt.npcSpriteSpec (NpcId 2) VillageArt.SouthFacing true 12L).Frame) + [] member _.ChimneySmokeFramesAreDeterministicAndThreePhase () = Assert.AreEqual(0, VillageArt.smokeFrameTick 0L) @@ -658,8 +686,8 @@ type PrototypeTests () = member _.RuntimeMovementAndNpcTargetsProduceStableSpriteDirections () = let idle = VillageArt.facingAfterMovement { X = 4.0f; Y = 4.0f } { X = 4.0f; Y = 4.0f } VillageArt.EastFacing let moved = VillageArt.facingAfterMovement { X = 4.0f; Y = 4.0f } { X = 2.0f; Y = 4.0f } VillageArt.EastFacing - let targetSpec = VillageArt.npcSpriteSpecAtTarget (NpcId 7) { X = 10.0f; Y = 10.0f } { X = 10.0f; Y = 8.0f } 4L - let arrivedSpec = VillageArt.npcSpriteSpecAtTarget (NpcId 7) { X = 10.0f; Y = 10.0f } { X = 10.0f; Y = 10.0f } 4L + let targetSpec = VillageArt.npcSpriteSpecAtTarget (NpcId 0) { X = 10.0f; Y = 10.0f } { X = 10.0f; Y = 8.0f } 4L + let arrivedSpec = VillageArt.npcSpriteSpecAtTarget (NpcId 0) { X = 10.0f; Y = 10.0f } { X = 10.0f; Y = 10.0f } 4L Assert.AreEqual(VillageArt.EastFacing, idle) Assert.AreEqual(VillageArt.WestFacing, moved) -- cgit v1.2.3