幻想森林

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 4327|回复: 3

[原创]在XNA游戏中显示汉字的各种方案

[复制链接]

3

主题

9

帖子

141

积分

③业余

积分
141
发表于 2007-11-3 15:41:24 | 显示全部楼层 |阅读模式
                    前几天,我在另外一篇日志(XNA游戏Marblets源码导读(二))里写道:目前还没有具体的解决方案,事实证明我错了,经过这两天的整理,我想在XNA游戏中显示汉字还是有很多方法的.

1.使用SpriteFont来显示汉字.

    在XNA1.0Refresh版中,新提供了SpriteFont来显示文字,但是首先我们需要将计算机中的字体转化成XNA可以识别的标准确FontDescription资源,这个转化过程,只会在我们的解决方案第一次生成的时候进行,会成成一个同名的xnb文件.我想和我在那篇日志提前的第二种方案相似吧.

    首先,我们来新建一个Windows Game解决方案,然后新追加一个Sprite Font,就保持默认名SpriteFont1.spritefont好了,打开进行编辑,修改以下两个地方.
程序代码<FontName>宋体</FontName>
程序代码<Start>& #19968;</Start>
<End>& #19999</End>
<!--<End>& #40869;</End>&#160;&#160;注意:&和#之间没有空格-->


&#160;&#160;&#160;&#160;宋体就是你计算机里面现在安装过的字体.

&#160;&#160;&#160;&#160;解释一下一的意义,在FontDescription里面,使用utf-8编码,一般情况下,中文简体汉字的编码可以认为在/u4E00~/u9FA5之间,共20901个.19968实际上就是/u4E00的十进制数,40869就是/u9FA5了.

&#160;&#160;&#160;&#160;本来,我是打算完全生成这20901个汉字,来看一下编译的时间和编译和文件的大小的.虽然我知道这个编译的过程很缓慢,但缓慢的出我意料 ,开始我预计在十来分钟左右可以完成,一直盯着计算机,想确认到一个准确的时间,后来我想有一个大概的时间就好了,再后来,我用进程管理器关掉了...我可以告诉你,这个过程超过50分钟...我的计算机是P41.73G,768M内存,如果你的"芯"够强劲,来自己试一下吧!

&#160;&#160;&#160;&#160;最终我设置成了19999, 也就是32个汉字,很快,数秒,编译后的xnb文件是65.9KB.

&#160;&#160;&#160;&#160;Game1里面,增加以下代码:
程序代码
public class Game1 : Microsoft.Xna.Framework.Game
&#160;&#160;&#160;&#160;{
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;... ...

&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;SpriteFont sprite;
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;SpriteBatch batch;
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;string font;


&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;protected override void LoadGraphicsContent(bool loadAllContent)
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;{
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;if (loadAllContent)
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;{

&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;batch = new SpriteBatch(this.graphics.GraphicsDevice);

&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;sprite = content.Load<SpriteFont>("SpriteFont1");

&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;for (int i = 19968; i <= 19999;i++ )
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;{
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;font += (Char)i;
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;}


&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;protected override void Draw(GameTime gameTime)
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;{
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;graphics.GraphicsDevice.Clear(Color.CornflowerBlue);

&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;batch.Begin();
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;batch.DrawString(sprite, font, new Vector2(0,0), Color.White);
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;batch.DrawString(sprite, font, new Vector2(0,30), Color.Red);
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;batch.End();

&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;this.graphics.GraphicsDevice.Present();

&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;base.Draw(gameTime);
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;}


最终效果如下:

&#160;&#160;&#160;&#160;

优点:
&#160;&#160;&#160;&#160;显示文字最方便,快速,想显示什么显示什么,PC/X360通用,各语种OS支持,便于做多语种游戏,英文游戏优先考虑.
缺点:
&#160;&#160;&#160;&#160;编译时间长,字体资源过大,完整20901个汉字估计要40M大小,再加上字号,粗斜体等效果,光一种宋体的资源就超过100M了,更别说多种字体.

2.使用字体图片来显示

&#160;&#160;&#160;&#160;这种方式是现在绝大多数游戏使用的方法,包括前面介绍的Marblets游戏也是使用这种方式,也是首先要制作一个资源图,以有一个索引表,方便的能找到要显示文字位置.

&#160;&#160;&#160;&#160;网上有很多软件能够实现自动的转化过程,包括微软也为XNA发布过这样的工具--Bitmap Font Maker Utility

优点:
&#160;&#160;&#160;&#160;字体资源比较小,显示也比较方便,PC/X360通用,各语种OS支持.
缺点:
&#160;&#160;&#160;&#160; 同样不适合字数比较多的中文.


3.实时生成图片加载显示

&#160;&#160;&#160;&#160;这种方式那天也提到过,不失为一种解决方案.

优点:
&#160;&#160;&#160;&#160; 不需要字体资源,直接使用系统字体,只要是电脑中安装有的字体样式都可以显示.
缺点:
&#160;&#160;&#160;&#160; 效率不高,只使用于PC,单语种(操作系统语言)

4.图片显示

&#160;&#160;&#160;&#160;最后一种方式就是提前把游戏中显要显示的文字提前做成图片了,直接在游戏里面显示.

优点:
&#160;&#160;&#160;&#160; PC/X360通用,各语种OS支持,英文游戏首先.
缺点:
&#160;&#160;&#160;&#160; 显示的文字信息多了就不行了.

总结:

能想到的也就这几种方式了,只能是根据自己的游戏类型来选择显示文字的方法了.

比如说文字量不多的小品游戏,第2,4两种方式就比较适合了.

如果是文量最多的RPG游戏的话,那就老老实实的使用第一种方式吧,不过,上面提出的缺点也并不是不可以克服掉,以下几种方式都有助你减小字体资源的体积:
&#160;&#160;&#160;&#160;1) 指定文字范围,只把游戏里面使用的文字编译.
&#160;&#160;&#160;&#160;2) 使用其它字体,比如我的计算机里面,方正超粗黑简体只有1.7M左右,而宋体却是10M左右,是因为方正里面的字体只有常用字还是什么原因,我不能确定,但我相信编译出来后的资源也一定相差在这个比例吧.

至于你只想开发英文版的游戏,当然是第1种方式是不二之选了.

还有其它好的汉字显示解决方案,欢迎大家讨论.                  
我的XNA学习足迹将记在这里 http://showim.net/blog/?cateID=4
回复

使用道具 举报

18

主题

428

帖子

5260

积分

⑦老手

在美工荒中挣扎的全能

积分
5260
QQ
发表于 2007-11-3 16:57:22 | 显示全部楼层
嘛,其实和是否使用XNA无关……这个算是东亚语言游戏的通病了,特别是AVG、RPG这类依赖文字的类型。
我们也是比较头痛这个问题,最后还是决定缓冲整个字体。
其实,相对来说.net应用本身内存就吃得比较大,那么相对来说三四十MB的额外消耗可能也就可以忽略吧,
反正把配置要求写高些,让玩家为之准备好相应的硬件吧。
(我们的东西虽然是没用.net,但是因为图形效果很复杂所以开销也应该不小,所以道理是一样的。)

还有就是,分页式预渲染字体的工作效率和编码也有关系。
比如说,如果编码方式令常用字分散在大量页面中,那么效率就会明显减低= v =好像在这种地方Unicode比较令人头痛。

另,实时描绘是不可行的,之前用Freetype+Irrlicht做了个实验,如果完全不缓存速度就是5fps以下。
嘛,进行缓冲是个有趣的方案,但我不知道连续几个字都要生成新字模的情况是否会对性能产生影响。
回复 支持 反对

使用道具 举报

3

主题

9

帖子

141

积分

③业余

积分
141
 楼主| 发表于 2007-11-3 21:47:49 | 显示全部楼层
倒不是觉得它运行的时候,多占几十M内存的问题,我想虽然是用XNA开发,但大部分人开发的游戏主要还是在PC上玩吧,开发一个本身才几M大小的小品游戏,感觉平白一下多出几十M的大小,很难接受.

不过回头看看现在的东西,动则1,2G,几十M的增加也许真的不算什么
我的XNA学习足迹将记在这里 http://showim.net/blog/?cateID=4
回复 支持 反对

使用道具 举报

18

主题

428

帖子

5260

积分

⑦老手

在美工荒中挣扎的全能

积分
5260
QQ
发表于 2007-11-3 22:19:43 | 显示全部楼层
不,小品的话增大太多会影响传播的。
我们这边是大项目所以无所谓= v =

如果平台限定PC的话倒是可以考虑这样做:在启动的时候读取Truetype字体,然后生成并缓冲所有字模。
这样也就是比读取图片素材多几秒钟的延迟吧。

这样,如果不用生僻字的话,用一个GB2312的字库就可以满足要求,一般不会过5M。
如果用Windows自带的字体就更省了。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|幻想森林

GMT+8, 2024-4-19 16:31 , Processed in 0.020976 second(s), 21 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表