summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/LivingVillage.Desktop.Tests/LivingVillage.Desktop.Tests.fsproj1
-rw-r--r--src/LivingVillage.Desktop.Tests/P75HudStripTests.fs59
-rw-r--r--src/LivingVillage.Desktop/Game.fs8
-rw-r--r--src/LivingVillage.Desktop/HudLayout.fs25
4 files changed, 81 insertions, 12 deletions
diff --git a/src/LivingVillage.Desktop.Tests/LivingVillage.Desktop.Tests.fsproj b/src/LivingVillage.Desktop.Tests/LivingVillage.Desktop.Tests.fsproj
index fb7ecb7..dc2cb23 100644
--- a/src/LivingVillage.Desktop.Tests/LivingVillage.Desktop.Tests.fsproj
+++ b/src/LivingVillage.Desktop.Tests/LivingVillage.Desktop.Tests.fsproj
@@ -46,6 +46,7 @@
<Compile Include="P72CharacterWalkTests.fs" />
<Compile Include="P73LightingTierTests.fs" />
<Compile Include="P74LaunchTransitionTests.fs" />
+ <Compile Include="P75HudStripTests.fs" />
<Compile Include="SampleTests.fs" />
</ItemGroup>
diff --git a/src/LivingVillage.Desktop.Tests/P75HudStripTests.fs b/src/LivingVillage.Desktop.Tests/P75HudStripTests.fs
new file mode 100644
index 0000000..e80d91f
--- /dev/null
+++ b/src/LivingVillage.Desktop.Tests/P75HudStripTests.fs
@@ -0,0 +1,59 @@
+namespace LivingVillage.Desktop.Tests
+
+open Microsoft.VisualStudio.TestTools.UnitTesting
+open LivingVillage.Desktop
+open LivingVillage.Kernel
+open LivingVillage.Kernel.Sim
+
+/// P75 回归:HUD 顶部条改为紧凑半透明药丸(去整宽深色带),信息不遮挡、文字可读。
+[<TestClass>]
+type P75HudStripTests () =
+
+ let world = Sim.initialWorldN 42UL 4
+ let control = SimulationControl.initial
+ let placed = HudLayout.layout (HudLayout.segments world control)
+
+ [<TestMethod>]
+ member _.TopBandIsRemovedForDayAndNight () =
+ for mode in [ Day; Night ] do
+ let palette = HudLayout.palette mode
+ Assert.AreEqual<byte>(0uy, palette.BarTop.A)
+ Assert.AreEqual<byte>(0uy, palette.BarBottom.A)
+ Assert.AreEqual<byte>(0uy, HudLayout.bandAlpha)
+
+ [<TestMethod>]
+ member _.PillsAreCompactInsideTheStrip () =
+ Assert.IsTrue(HudLayout.pillHeight < HudLayout.barHeight, "药丸须比窄条矮,留出上下留白")
+ for (x, width, _) in placed do
+ let pill = HudLayout.segmentBackdrop x width
+ Assert.IsTrue(pill.Y >= 0 && pill.Y + pill.Height <= HudLayout.barHeight, "药丸须在窄条内")
+ let hair = HudLayout.pillHairline x width
+ Assert.IsTrue(hair.Height = 1, "发丝线为 1px")
+ Assert.IsTrue(hair.X >= pill.X && hair.X + hair.Width <= pill.X + pill.Width, "发丝线须在药丸内")
+ Assert.AreEqual<int>(max 1 (pill.Width - 2), hair.Width)
+
+ [<TestMethod>]
+ member _.StripLeavesWhitespaceAndDoesNotOverlapDateCard () =
+ Assert.IsTrue(placed.Length > 0)
+ let firstX = placed |> List.head |> fun (x, _, _) -> x
+ Assert.AreEqual<int>(HudLayout.paddingX, firstX)
+ let lastEnd = placed |> List.last |> fun (x, width, _) -> x + width
+ // 药丸总跨度远小于通栏宽度,右侧留白充足(不再铺满整宽)。
+ Assert.IsTrue(lastEnd < 1280 / 2, sprintf "HUD 只占左半,右侧留白;lastEnd=%d" lastEnd)
+ let reading = HudLayout.calendarReading world.Tick
+ let cal = HudLayout.calendarCardRect 1280 reading
+ Assert.IsTrue(cal.Y >= HudLayout.barHeight + HudLayout.accentHeight, "日历卡不压顶部条")
+
+ [<TestMethod>]
+ member _.TextStaysReadableOnTranslucentPills () =
+ for mode in [ Day; Night ] do
+ let palette = HudLayout.palette mode
+ Assert.IsTrue(palette.SegmentBackdrop.A > 0uy && palette.SegmentBackdrop.A < 255uy, "药丸半透明")
+ let valueLuma = int palette.Value.R + int palette.Value.G + int palette.Value.B
+ let outlineLuma = int palette.Outline.R + int palette.Outline.G + int palette.Outline.B
+ Assert.IsTrue(valueLuma > 600, "数值色须够亮")
+ Assert.IsTrue(valueLuma > outlineLuma + 400, "亮字 vs 深描边对比须足够")
+ // 图标与数值并排:文本起始在图标右侧。
+ for (x, _, segment) in placed do
+ Assert.AreEqual<int>(x + HudLayout.iconWidth + HudLayout.iconGap, HudLayout.textOrigin x)
+ Assert.IsFalse(System.String.IsNullOrEmpty segment.Value)
diff --git a/src/LivingVillage.Desktop/Game.fs b/src/LivingVillage.Desktop/Game.fs
index a4f994b..c6408aa 100644
--- a/src/LivingVillage.Desktop/Game.fs
+++ b/src/LivingVillage.Desktop/Game.fs
@@ -3405,17 +3405,14 @@ type LivingVillageGame() as this =
/// 顶部窄信息条:时段/时间/倍速/体力/钱币,半透明渐变 + 强调线,绝非大黑块。
member private this.DrawHudBar() =
- let viewport = this.GraphicsDevice.Viewport
let profile = M6Presentation.profileAtTick world.Tick
let palette = HudLayout.palette profile.Mode
let placed = HudLayout.layout (HudLayout.segments world simulationControl)
let barHeight = HudLayout.barHeight
let textY = (barHeight - 8 * HudLayout.textScale) / 2
spriteBatch.Begin()
- // 竖向渐变:上半略亮、下半压暗,避免整条纯色。
- spriteBatch.Draw(pixel, Rectangle(0, 0, viewport.Width, barHeight / 2), palette.BarTop)
- spriteBatch.Draw(pixel, Rectangle(0, barHeight / 2, viewport.Width, barHeight - barHeight / 2), palette.BarBottom)
- spriteBatch.Draw(pixel, Rectangle(0, barHeight, viewport.Width, HudLayout.accentHeight), palette.Accent)
+ // P75:去掉整宽深色渐变带(palette 的 BarTop/BarBottom alpha=0),信息只靠各段的
+ // 半透明药丸承载——紧凑的图标+数值并排、留白充足,HUD 区域黑块面积大幅下降。
// 图标用 pixel 贴图按 7x7 点阵绘制(无外部素材),先描边后填充,保证昼夜可读。
let drawIcon (iconX: int) (iconY: int) (color: Color) (icon: HudLayout.HudIcon) =
HudLayout.iconRows icon
@@ -3434,6 +3431,7 @@ type LivingVillageGame() as this =
let iconY = (barHeight - HudLayout.iconHeight) / 2
for (x, width, segment) in placed do
spriteBatch.Draw(pixel, HudLayout.segmentBackdrop x width, palette.SegmentBackdrop)
+ spriteBatch.Draw(pixel, HudLayout.pillHairline x width, palette.Accent)
let textX = HudLayout.textOrigin x
let labelAdvanced = FloatingPrompt.measureWidth (segment.Label + " ") HudLayout.textScale
let isEnergy = segment.Icon = HudLayout.EnergyIcon
diff --git a/src/LivingVillage.Desktop/HudLayout.fs b/src/LivingVillage.Desktop/HudLayout.fs
index b19df4b..cd06224 100644
--- a/src/LivingVillage.Desktop/HudLayout.fs
+++ b/src/LivingVillage.Desktop/HudLayout.fs
@@ -122,6 +122,17 @@ module HudLayout =
let y = (barHeight - height) / 2
Microsoft.Xna.Framework.Rectangle(x - 6, y, width + 12, height)
+ /// P75:药丸底部 1px 强调发丝线(取代整条铺满的 accent 带,让留白更足)。
+ let pillHairline (x: int) (width: int) : Microsoft.Xna.Framework.Rectangle =
+ let pill = segmentBackdrop x width
+ Microsoft.Xna.Framework.Rectangle(pill.X + 1, pill.Y + pill.Height - 2, max 1 (pill.Width - 2), 1)
+
+ /// P75:顶部不再铺整宽深色带(0 = 仅靠半透明药丸承载信息,去掉「整块深色底」)。
+ let bandAlpha : byte = 0uy
+
+ /// P75:药丸高度的紧凑上界(须 < barHeight 以留出上下留白)。
+ let pillHeight : int = 8 * textScale + 10
+
type Palette =
{ BarTop: Color
BarBottom: Color
@@ -131,25 +142,25 @@ module HudLayout =
SegmentBackdrop: Color
Outline: Color }
- /// 白天暖色 / 夜晚(冬夜)冷色微调;均为半透明渐变窄条,无大黑块。
- /// 每个常驻片段再叠一层半透明底色 + 1px 深色描边,双时段都能读清。
+ /// 白天暖色 / 夜晚(冬夜)冷色微调;半透明药丸承载信息,无整宽深色带、无大黑块。
+ /// P75 起 `BarTop/BarBottom` 保留字段但 alpha=0(不再铺整条底色)。
let palette (mode: M6DayNight) : Palette =
match mode with
| Day ->
- { BarTop = Color(40, 56, 62, 200)
- BarBottom = Color(22, 34, 40, 200)
+ { BarTop = Color(40, 56, 62, 0)
+ BarBottom = Color(22, 34, 40, 0)
Accent = Color(212, 168, 96)
Label = Color(206, 220, 208)
Value = Color(242, 248, 234)
SegmentBackdrop = Color(8, 14, 20, 150)
Outline = Color(6, 10, 14, 255) }
| Night ->
- { BarTop = Color(22, 30, 48, 205)
- BarBottom = Color(13, 19, 33, 205)
+ { BarTop = Color(22, 30, 48, 0)
+ BarBottom = Color(13, 19, 33, 0)
Accent = Color(120, 168, 196)
Label = Color(176, 196, 214)
Value = Color(228, 238, 246)
- SegmentBackdrop = Color(4, 8, 16, 160)
+ SegmentBackdrop = Color(4, 8, 16, 170)
Outline = Color(3, 6, 12, 255) }
// ---- P43:右上日历钟卡(纯模型;季节/天数/时段/时钟全部由真实 tick 导出)----