namespace LivingVillage.Desktop.Tests open Microsoft.VisualStudio.TestTools.UnitTesting open Microsoft.Xna.Framework open LivingVillage.Desktop /// P79 夜帧整改回归(纯函数层): /// * 去叠光晕:单光源 ≤2 层视觉层(内芯 + 外环),芯/环之间确定暗隙,半径收紧到 3 tile; /// * 夜帧炊烟增强:烟柱分段 + 外发光,夜帧 alpha 明显高于白天,白天零回归。 [] type P79NightPolishTests () = let map = MapGen.generate (MapGen.defaultParams 42UL) [] member _.HaloRingHasTwoVisualLayersAndADarkGap () = let cx, cy, radius, peak = 100, 100, 96, 118 let layers = VillageArt.haloRingLayers cx cy radius peak Assert.IsTrue(not (List.isEmpty layers), "光晕须发出图元") Assert.IsTrue( (layers = VillageArt.haloRingLayers cx cy radius peak), "光晕须确定性") Assert.IsTrue((SceneDetail.nightHaloVisualLayers = 2), "每光源最多 2 层视觉层") let covers px py = layers |> List.exists (fun (rect, _) -> rect.X <= px && px < rect.X + rect.Width && rect.Y <= py && py < rect.Y + rect.Height) // 内芯亮、外环亮,芯环之间留一圈暗隙(同排 dy=0)。 Assert.IsTrue(covers cx cy, "内芯须被点亮") Assert.IsTrue(covers (cx + 10) cy, "内芯直径内须被点亮") let innerRadius = radius * 2 / 5 let gapRadius = max (innerRadius + 2) (radius * 3 / 5) let gapMid = cx + (innerRadius + gapRadius) / 2 Assert.IsFalse(covers gapMid cy, "芯环之间须留暗隙") Assert.IsFalse(covers (cx - (gapMid - cx)) cy, "暗隙须左右对称") Assert.IsTrue(covers (cx + (gapRadius + radius) / 2) cy, "外环须被点亮") // 外环不得越过半径、不得出现方角。 for (rect, _) in layers do Assert.IsTrue(abs (rect.X + rect.Width / 2 - cx) <= radius + 1, "图元须在半径内") Assert.IsFalse(covers (cx + radius) (cy + radius), "四角须保持为空:圆形非方斑") [] member _.NightHaloIsTighterAndCapped () = Assert.IsTrue((SceneDetail.nightHaloRadiusTiles = 3), "去叠后半径须收紧到 3 tile") Assert.IsTrue((SceneDetail.nightHaloRadiusTiles < 4), "须比旧半径 4 tile 更紧") Assert.IsTrue((SceneDetail.nightHaloPeakAlphaAt 0.0f) = 0, "白天光晕须为 0(零回归)") Assert.IsTrue((SceneDetail.nightHaloPeakAlphaAt 1.0f) > 0, "夜帧光晕须可见") [] member _.NightSmokeColumnAndGlowAreStrongerThanDay () = Assert.IsTrue((SceneDetail.nightSmokeSegments >= 2), "夜帧烟柱须分段堆叠") Assert.IsTrue((SceneDetail.nightSmokeSegmentLift > 0), "每段须向上抬升") Assert.IsTrue( (SceneDetail.nightSmokeAlphaAt 1.0f) > (SceneDetail.smokeAlphaAt 1.0f), "夜帧烟柱 alpha 须高于白天 underlay") Assert.IsTrue((SceneDetail.nightSmokeGlowPeakAt 1.0f) > (SceneDetail.nightSmokeGlowPeakAt 0.0f), "夜帧外发光须更强") Assert.IsTrue(SceneDetail.nightSmokeGlowRadius > 0, "外发光半径须为正") let sources = SceneDetail.smokeSourceTiles map Assert.IsTrue(not (List.isEmpty sources), "须仍能取到炊烟源")