summaryrefslogtreecommitdiff
path: root/src/LivingVillage.Desktop/Game.fs
diff options
context:
space:
mode:
authorSomhairle H. Marisol <[email protected]>2026-09-21 12:05:26 +0800
committerSomhairle H. Marisol <[email protected]>2026-09-21 12:05:26 +0800
commit2851a030db0f0bc5892305fb189a41c97c13578d (patch)
treedbb834c31ad43777fd43f39c00f58449cb753388 /src/LivingVillage.Desktop/Game.fs
parent3812e78ba39764b3844d52ee7382b1350960ecb9 (diff)
downloadliving-village-2851a030db0f0bc5892305fb189a41c97c13578d.tar.gz
fix(desktop): 标题菜单光标与文字分列不再叠印
根因:页面标题行(panelY+24)与首行内容(MenuTopY)同为 y=320 造成两串文字叠印。修复:TitleScreen 布局新增 HeadingY/FirstItemY 分层与独立光标列(CursorX/CursorWidth/TextX),selectionRects 纯函数返回光标与文字矩形,回归测试断言逐行矩形不相交且标题行净空≥32px;渲染改为光标、文字分别绘制。
Diffstat (limited to 'src/LivingVillage.Desktop/Game.fs')
-rw-r--r--src/LivingVillage.Desktop/Game.fs18
1 files changed, 11 insertions, 7 deletions
diff --git a/src/LivingVillage.Desktop/Game.fs b/src/LivingVillage.Desktop/Game.fs
index c8d0044..7337129 100644
--- a/src/LivingVillage.Desktop/Game.fs
+++ b/src/LivingVillage.Desktop/Game.fs
@@ -560,8 +560,12 @@ type LivingVillageGame() as this =
PixelText.draw spriteBatch pixel cjkAtlas x y textScale color text
let drawSelection (index: int) (label: string) (y: int) =
let selected = index = menu.Selected
- let prefix = if selected then ">" else " "
- drawText innerX y (if selected then selectedColor else textColor) (sprintf "%s %s" prefix label)
+ let cursor, labelRect = TitleScreen.selectionRects layout index
+ if selected then
+ PixelText.draw spriteBatch pixel cjkAtlas cursor.X cursor.Y textScale selectedColor ">"
+ else
+ PixelText.draw spriteBatch pixel cjkAtlas cursor.X cursor.Y textScale mutedColor " "
+ PixelText.draw spriteBatch pixel cjkAtlas labelRect.X labelRect.Y textScale (if selected then selectedColor else textColor) label
spriteBatch.Begin()
// Layered dusk gradient: sky bands darken toward the horizon, never a flat block.
@@ -601,27 +605,27 @@ type LivingVillageGame() as this =
// Menu panel floats over the lower half; translucent so the scene layers stay visible.
spriteBatch.Draw(pixel, Rectangle(panelX, panelY, panelWidth, panelHeight), Color(11, 19, 27, 200))
spriteBatch.Draw(pixel, Rectangle(panelX, panelY, panelWidth, 4), Color(92, 180, 190))
- let contentY = layout.MenuTopY
+ let contentY = layout.FirstItemY
match menu.Page with
| MainMenu ->
- drawText innerX (panelY + 24) mutedColor (ChineseText.menuHeading MainMenuHeading)
+ drawText innerX (layout.HeadingY) mutedColor (ChineseText.menuHeading MainMenuHeading)
MenuState.items menu
|> List.iteri (fun index item -> drawSelection index (MenuState.itemLabel item) (contentY + index * lineHeight))
drawText innerX (panelY + panelHeight - 40) mutedColor "UP DOWN 选择 ENTER 确认"
| Settings ->
- drawText innerX (panelY + 24) mutedColor (ChineseText.menuHeading SettingsHeading)
+ drawText innerX (layout.HeadingY) mutedColor (ChineseText.menuHeading SettingsHeading)
MenuState.settings
|> List.iteri (fun index setting -> drawSelection index (MenuState.settingsLabel setting) (contentY + index * lineHeight))
drawText innerX (panelY + panelHeight - 72) mutedColor (sprintf "当前 %s" (M6Presentation.clockLabel menu.Settings))
drawText innerX (panelY + panelHeight - 40) mutedColor "ENTER 应用 ESC 返回"
| Controls ->
- drawText innerX (panelY + 24) mutedColor (ChineseText.menuHeading ControlsHeading)
+ drawText innerX (layout.HeadingY) mutedColor (ChineseText.menuHeading ControlsHeading)
MenuState.controlRows
|> List.iteri (fun index row ->
drawText innerX (contentY + index * 25) textColor (sprintf "%s %s" row.Keys row.Action))
drawText innerX (panelY + panelHeight - 40) mutedColor "ESC 返回"
| LoadError ->
- drawText innerX (panelY + 24) (Color(240, 130, 120)) "读取失败"
+ drawText innerX (layout.HeadingY) (Color(240, 130, 120)) "读取失败"
let message = menu.Error |> Option.defaultValue "暂无存档"
let visible = if message.Length > 24 then message.Substring(0, 24) else message
drawText innerX contentY textColor visible