summaryrefslogtreecommitdiff
path: root/src/LivingVillage.Desktop/CjkGlyphAtlas.fs
diff options
context:
space:
mode:
authorSomhairle H. Marisol <[email protected]>2026-09-21 00:26:30 +0800
committerSomhairle H. Marisol <[email protected]>2026-09-21 00:26:30 +0800
commitb6b95988e525a68ea7426ecc9690b18a1b3bbfe8 (patch)
tree4c19ab58a610c6d783e1dfc45585b12a6ecb2e58 /src/LivingVillage.Desktop/CjkGlyphAtlas.fs
parent0ea26337830ada438df144b3a51f429f00dc1967 (diff)
downloadliving-village-b6b95988e525a68ea7426ecc9690b18a1b3bbfe8.tar.gz
feat(m6c): 完成江南村庄中文交付
完成江南村庄场景、角色表现和中文界面的 M6c 交付范围。 新增 CJK 字形图集、中文文案与运行时加载,补充民居情境交互和确定性村庄美术表现。 更新资源复制与 Linux/macOS 打包校验,加入 188 字符清单、资源许可说明和对应原型测试。 补充江南美术方向与 M6c 交付说明,并保持原有模拟内核和桌面构建入口不变。
Diffstat (limited to 'src/LivingVillage.Desktop/CjkGlyphAtlas.fs')
-rw-r--r--src/LivingVillage.Desktop/CjkGlyphAtlas.fs55
1 files changed, 55 insertions, 0 deletions
diff --git a/src/LivingVillage.Desktop/CjkGlyphAtlas.fs b/src/LivingVillage.Desktop/CjkGlyphAtlas.fs
new file mode 100644
index 0000000..e21f025
--- /dev/null
+++ b/src/LivingVillage.Desktop/CjkGlyphAtlas.fs
@@ -0,0 +1,55 @@
+namespace LivingVillage.Desktop
+
+open System
+open System.IO
+open Microsoft.Xna.Framework
+open Microsoft.Xna.Framework.Graphics
+
+module CjkGlyphAtlas =
+ let columns = 16
+ let cellPixels = 24
+
+ // Keep this table sorted and stable so the generated PNG has a reproducible layout.
+ let private characterTable =
+ "一不主乐乡买于互交人从价传作使保倍停入关内准出到前力功动助单卖南原友取可同和回围圃在墙备夜大天失好始存完家察对就层居已年庄库应度开式当录得心必态怒总恼意戏成或打找报拒择挑据提播操效敌数新方无时明易是晚景暂更最有村板林标档桥歉民水求江没法游物状瓦用留白目石确社离移竹笑精系紧给绝继绪续置聊能范获菜衅观认讨议记讲设话说请读谅败资足近还进迫退选速道量金鉴钱闭闲闻附零需面项须食饥饿黛"
+
+ let characters = characterTable.ToCharArray()
+ let rowCount = (characters.Length + columns - 1) / columns
+ let pixelWidth = columns * cellPixels
+ let pixelHeight = rowCount * cellPixels
+ let assetRelativePath = "Assets/cjk-glyph-atlas.png"
+ let manifestRelativePath = "Assets/cjk-glyphs.txt"
+
+ let private indices =
+ characters
+ |> Array.mapi (fun index character -> character, index)
+ |> Map.ofArray
+
+ let contains (character: char) = Map.containsKey character indices
+
+ let sourceRectangle (character: char) =
+ indices
+ |> Map.tryFind character
+ |> Option.map (fun index ->
+ Rectangle(
+ (index % columns) * cellPixels,
+ (index / columns) * cellPixels,
+ cellPixels,
+ cellPixels))
+
+ let runtimeAssetPath () = Path.Combine(AppContext.BaseDirectory, assetRelativePath)
+
+ let runtimeManifestPath () = Path.Combine(AppContext.BaseDirectory, manifestRelativePath)
+
+ let load (device: GraphicsDevice) : Texture2D =
+ let path = runtimeAssetPath ()
+ if not (File.Exists path) then
+ raise (FileNotFoundException(sprintf "CJK glyph atlas is missing: %s" path, path))
+
+ use stream = File.OpenRead path
+ let texture = Texture2D.FromStream(device, stream)
+ if texture.Width <> pixelWidth || texture.Height <> pixelHeight then
+ texture.Dispose()
+ invalidOp (sprintf "CJK glyph atlas has dimensions %dx%d; expected %dx%d." texture.Width texture.Height pixelWidth pixelHeight)
+ else
+ texture