Skip to content

文本与字体

《渡口夜话》带妆彩排那天,台口裱好的字幕框一直空着——九宫格的画框是第 15 章的手艺,词儿却还在编剧秋白的手稿上。这天他把稿子拍在桌上:“第二幕的词都齐了。上字幕。”

这一章把文字搬进 2D 世界。文字看起来是个简单需求——“在屏幕上写一行字”——但游戏里的文字活在渲染管线里:字体是资产,字形要光栅化成纹理,排版要处理换行与对齐,伤害飘字还得会动、会淡出。一路拆开:

  • 第一行字与满屏豆腐——Text2d 三分钟上手,然后亲眼看中文变成一排豆腐块:默认字体只认 95 个 ASCII 字符,而且这事一声不吭;
  • 字模也是资产——字体文件用 AssetServer 加载,TextFont 指定用哪副字模、刻多大字号;顺带交代本书的中文字体从哪来、为什么要子集化;
  • 字号的真相——font_size 是“按多大字号刻字模”,Transform 缩放是“把照片放大”;行高 LineHeight 与磨边 FontSmoothing 两个旋钮;
  • 把词排进框——TextBounds 给文字画地界,LineBreak 定换行规矩,Justify 管行与行的对齐,与 Anchor 各司其职;
  • 提词器——运行时改 Text2d 字符串,排版自动跟上:一个打字机效果;
  • 富文本——TextSpan 把一块文本拆成多段,各管各的字体、颜色、下划线、删除线、底色,外加整块的影子 Text2dShadow
  • 台上的字与玻璃上的字——同一套样式组件在 UI 里的镜像 Text,第 28 章的预告;
  • 夜战——综合战:阿燕劈木人桩,每一击触发 Event(第 8 章),Observer 当场铸出会上飘、会淡出的伤害数字,连击牌用 Text2dWriter 实时改字。

这些类型住在 bevy_text(排版引擎与样式组件)和 bevy_spriteText2d 本体)里,用的时候照旧从 bevy::prelude 来,少数几个(TextBoundsLineHeightFontSmoothing 等)要从 bevy::text 显式引入。

配套 crate 是 code/ch16-textassets/fonts/ 里有两个中文字体文件——它们是 Noto Sans SC 的子集(GB2312 字符集,每个约 1.9 MB),由 scripts/make_ch16_assets.py 下载原始字体、裁剪并按 OFL 许可证的要求改名生成,仓库里已经备好,许可证全文见同目录的 OFL.txt。木人桩和阿燕的练剑帧沿用第 15 章的调色板,也出自同一个脚本。为什么字体要这么折腾,下一节撞了墙你就明白了。