ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

raylib 多语言显示实战:从 0 到 1 让中日俄文不再乱码

raylib 多语言显示实战:从 0 到 1 让中日俄文不再乱码 raylib 多语言显示实战从 0 到 1 让中日俄文不再乱码【免费下载链接】raylibA simple and easy-to-use library to enjoy videogames programming项目地址: https://gitcode.com/GitHub_Trending/ra/raylib做游戏出海时最尴尬的画面往往是英文版一切正常切到中文、俄文后满屏问号。raylib 并没有内置多语言开关它的核心是字体图集机制——哪些字形被打包进字体纹理完全由你通过码点列表决定。搞懂这个机制后用不到 50 行代码就能让窗口同时渲染六种语言。为什么非英文会乱码字体图集机制速览raylib 里的Font本质上是一张纹理图集加一份字符元数据所有字形位图被打包进font.texture每个字符的偏移、步进信息存在font.glyphs数组里。LoadFont加载时默认只烘焙 Basic ASCII码点 32~127这 96 个字符中日韩字符位于更靠后的码点区间图集里没有对应字形画出来自然是方框或问号。解决办法是LoadFontEx传入一份码点列表raylib 会把字体文件中这些码点字形重新打包成图集。// LoadFont 默认只加载 Basic ASCII [32-127] Font font LoadFont(resources/NotoSansTC-Regular.ttf); // LoadFontEx 可自定义码点列表第 3/4 参传 NULL/0 即为默认行为 Font font2 LoadFontEx(resources/NotoSansTC-Regular.ttf, 32, codepoints, count);各语言常用码点区间对照摘自示例examples/text/text_unicode_ranges.c实际加载的范围语言/区域码点区间中文CJK 基本汉字0x4E00 ~ 0x9FFF日文平假名0x3040 ~ 0x309F日文片假名0x30A0 ~ 0x30FF韩文0xAC00 ~ 0xD7AF俄文西里尔0x0400 ~ 0x4FF欧洲语言扩展拉丁0xC0 ~ 0x17F动手实现四步跑通多语言文本渲染1. 确认字体文件覆盖目标语言图集的上限取决于字体文件本身——文件里没有的字形码点加得再多也没用。仓库examples/text/resources/下自带了几个可用的开源字体NotoSansTC-Regular.ttf覆盖拉丁、希腊、西里尔与 CJK 字符官方多语言示例用的就是它DotGothic16-Regular.ttf日文哥特体像素风KAISG.ttf、anonymous_pro_bold.ttf、pixantiqua.ttf其他风格备选注意示例代码里写的是resources/NotoSansTC-Regular.ttf因为示例的工作目录是examples/text/这个相对路径实际指向仓库里的examples/text/resources/目录。2. 加载字体并设置缩放过滤目的先把字体加载进显存并为后续放大做准备。// fontSize 是字形像素高度codepoints 传 NULL/0 表示加载默认 ASCII 集 Font font LoadFontEx(resources/NotoSansTC-Regular.ttf, 32, NULL, 0); // 双线性过滤缩放渲染时字形边缘更平滑 SetTextureFilter(font.texture, TEXTURE_FILTER_BILINEAR);加载完成后font.texture就是图集纹理font.glyphCount告诉你当前图集里有多少个字形——这个值后面验证加载效果会用到。3. 为目标语言追加码点区间目的在已有字体上追加指定语言区间而不是一次性写死。下面这段逻辑来自examples/text/text_unicode_ranges.c里的AddCodepointRange辅助函数// 把 [start, stop] 区间追加进已有字体先拷贝旧码点再拼上新区间重建图集 int *updatedCodepoints RL_CALLOC(currentRangeSize rangeSize, sizeof(int)); for (int i 0; i currentRangeSize; i) updatedCodepoints[i] font-glyphs[i].value; // 保留原有码点 for (int i currentRangeSize; i updatedCodepointCount; i) updatedCodepoints[i] start (i - currentRangeSize); // 追加新区间 UnloadFont(*font); *font LoadFontEx(fontPath, 32, updatedCodepoints, updatedCodepointCount);之后按需调用即可示例中一次可叠加多个区间AddCodepointRange(font, resources/NotoSansTC-Regular.ttf, 0x4e00, 0x9fff); // 中文 AddCodepointRange(font, resources/NotoSansTC-Regular.ttf, 0x3040, 0x309f); // 平假名关键参数是start/stop两个码点边界区间内的每个码点都会生成一个字形所以区间越大、图集越慢后面避坑指南会讲。4. 用 DrawTextEx 渲染多语言文本目的验证图集是否生效。DrawTextEx接受字体、文本、位置、像素字号、字距、颜色六个参数文本以 UTF-8 传入BeginDrawing(); ClearBackground(RAYWHITE); DrawTextEx(font, English: Hello World!, (Vector2){50, 70}, 32, 1, DARKGRAY); DrawTextEx(font, 中文: 你好世界!, (Vector2){50, 270}, 32, 1, DARKGRAY); DrawTextEx(font, 日本語: こんにちは世界!, (Vector2){50, 320}, 32, 1, DARKGRAY); EndDrawing();示例窗口还会把图集纹理放大画在右侧并显示CODEPOINTS GLYPHS LOADED计数按下 1~4 键可实时切换欧洲/希腊/西里尔/CJK 语言集效果如下5. 性能调优只加载实际用到的字符目的避免一次性烘焙上万个 CJK 码点导致加载卡顿。更省的做法是反过来——先扫描游戏里所有文本提取实际用到的码点再去生成图集这正是examples/text/text_codepoints_loading.c的思路// 从全部游戏文本中提取码点源文件需保存为 UTF-8 int codepointCount 0; int *codepoints LoadCodepoints(text, codepointCount); // 去重后再生成图集图集只包含真正用到的字形 int *noDups CodepointRemoveDuplicates(codepoints, codepointCount, noDupsCount); Font font LoadFontEx(resources/DotGothic16-Regular.ttf, 36, noDups, noDupsCount);示例中的整首伊吕波歌含 75 个字符去重后只剩约 50 个码点图集体积和生成时间都减半空格键可随时切换查看生成的图集进阶玩法搭一个轻量语言管理层场景语言集加载好之后文本散落在各处的DrawTextEx调用里切换语言就要逐个改字符串。方案把文案收敛到一张按语言索引的扁平表里渲染处只引用编号。const char *TEXTS[2][4] { { My Game, Start, Pause, Quit }, // 英语 { 我的游戏, 开始, 暂停, 退出 } // 中文 }; const char *GetText(int lang, int id) { return TEXTS[lang][id]; }场景文案需要策划可维护不想动代码。方案改用 JSON 配置用 raylib 的文件 API 读入可参考examples/core/core_directory_files.c的文件读取方式{ en: { title: My Game, start: Start }, zh: { title: 我的游戏, start: 开始游戏 } }表情符号也是同一套机制——给字体加上对应码点区间即可渲染示例效果可见examples/text/text_unicode_emojis.c避坑指南加载了字体部分字符还是方框。两个可能码点区间没覆盖该字符或者字体文件本身不含这个字形——text_unicode_ranges.c里明确警告过仓库自带的 NotoSansTC 并不含天城文、阿拉伯文、希伯来文。先选覆盖目标语言的字体再用font.glyphCount验证加载结果。代码能编译屏幕上中文却是一串问号。这是源码文件编码问题Windows 下编辑器常以 GBK 保存而 raylib 按 UTF-8 解析字符串。text_codepoints_loading.c的注释特意提醒must be UTF-8把工程统一设为 UTF-8无 BOM即可。切换语言集时画面卡住好几秒。一次性加载数千个 CJK 码点需要重新烘焙整张图集示例为此专门画了 GENERATING FONT ATLAS... 的遮罩层。两个对策用LoadCodepoints把范围收窄到实际用到的字符或在过场时预加载下一语言的字体切完再UnloadFont旧的。延伸阅读examples/text/text_unicode_ranges.c — 完整示例按 1~4 键切换欧洲/希腊/西里尔/CJK 码点集examples/text/text_codepoints_loading.c — 从文本自动提取码点生成最小字体图集examples/text/text_unicode_emojis.c — 表情符号的加载与渲染src/raylib.h — 搜索LoadFontEx、LoadCodepoints、DrawTextEx查字体相关 API 的完整参数说明下一篇可以看看examples/text/text_font_sdf.c里的 SDF 字体——它能让任意缩放字号下的文字边缘依然锐利做多语言 UI 时配合本文的码点管理会非常顺手。觉得有用顺手点个赞吧。【免费下载链接】raylibA simple and easy-to-use library to enjoy videogames programming项目地址: https://gitcode.com/GitHub_Trending/ra/raylib创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表