Xna不同于DirectX,因其内部并未提供类似于D3DFont的机制(据说之所以会这样做,也是考虑到与Xbox360兼容的缘故),使得显示中文变得极为不便。

虽然如此,要实现Xna下的中文显示依然存在多种方法:

1.添加SpriteFont,修该他的CharacterRegion的Start和End,范围就是中文的Unicode范围。

因为通常大家不太好定位自己所需汉字的Unicode范围,而该范围又不允许无限制扩大,因此不可取~

2.GDI+

使用GDI+虽然能够满足中文显示的要求,但众所周知,GDI+本身的效率是个问题,因此,也不建议大家使用这种方法。

相关内容,请参考:http://www.cnblogs.com/XnaZero/archive/2009/03/29/1412148.html ,为XnaZero兄原创~

XNA3.0内带例子 SpriteFontX_1_0_2_1.rar

XNA3.1内带例子 SpriteFontX_1_0_2_1_For_Xna3_1.rar

XNA4.0内带例子 SpriteFontX_1_0_2_2_For_Xna4.rar

XNA支持中文输入示例 http://xna.omgsoft.com.cn/education/XNA_IME.aspx (Xna游戏世界)

作者没有开源,因此不太清楚内部机制,但个人猜想核心部分或许是这样的:

using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System.IO;
using AppColor = System.Drawing.Color;
using XnaColor = Microsoft.Xna.Framework.Graphics.Color;
namespace FontDemo
{
/// <summary>
/// by kenkao(http://blog.csdn.net/kenkao)
/// </summary>
///
public class ChFont
{
static Graphics graphics;
static GraphicsDevice graphicsDevice;
static MemoryStream stream = new MemoryStream();
public ChFont(Game game)
{
graphics = Graphics.FromHwnd(game.Window.Handle);
graphicsDevice = game.GraphicsDevice;
}
/// <summary>
/// 生成中文纹理(by gdi+)
/// </summary>
/// <param name="graphicsDevice">图形设备</param>
/// <param name="Text">文字</param>
/// <param name="font">字体</param>
/// <param name="FontColor">字体前景色</param>
/// <returns>所得纹理</returns>
public Texture2D CreateChFont(string Text, Font font, AppColor FontColor)
{
Texture2D ChTexture;
try
{
//---生成字体
SizeF ef = graphics.MeasureString(Text, font);
Bitmap bitmap = new Bitmap((int)ef.Width, (int)ef.Height);
graphics = Graphics.FromImage(bitmap);
graphics.DrawString(Text, font, new SolidBrush(FontColor), new PointF());
bitmap.Save(stream, ImageFormat.Png); //---注意:这里使用MemoryStream作为gid+与Xna的平行接口
stream.Seek(0L, SeekOrigin.Begin);
ChTexture = Texture2D.FromFile(graphicsDevice, stream); //---不要妄图使用file,否则效率会非常令人纠结的^^
return ChTexture;
}
catch
{
return null;
}
}
}
}

调用方法生成中文纹理,而后使用SpriteBatch绘制即可~

3.字体纹理

相比以上两种方法而言,这种方法算是较为正统的Xna中文显示方法,借用Xna的ContentPipeline,这种方法的效率算是比较不错的。此种方法较为可取。

相关内容,请参考:http://kb.cnblogs.com/a/1459016/,为clayman兄原创~

其实要实现所谓的字体纹理,关键的核心方法有两个:

public class Texture2D : Texture
{
public void GetData<T>(T[] data);
public void GetData<T>(T[] data, int startIndex, int elementCount);
public void GetData<T>(int level, Rectangle? rect, T[] data, int startIndex, int elementCount);
public void SetData<T>(T[] data); public void SetData<T>(T[] data, int startIndex, int elementCount, SetDataOptions options);
public void SetData<T>(int level, Rectangle? rect, T[] data, int startIndex, int elementCount, SetDataOptions options);
}

而追根究底,这两个方法实现的其实就是纹理间内存数据的拷贝而已。

整个方法原理如下:

1.准备好事先生成的“字库”(可以用Gdi+,好像还有一个开源的工具叫做ttf2bmp),其实就是带有通用中文字符的纹理。

2.程序启动时,通过内容管线,事先将其加载到内存,也就是一个Texture2D对象里。这里我们称作原始纹理。

3.需要绘制中文字符时,事先new一个空白的Texture2D。这里我们称作目标纹理。

4.根据字符的位置对应关系,从原始纹理中截取所要绘制的字符数据,赋值给目标纹理。

5.绘制目标纹理即可。

如上方法中,用到的其实也仅仅就是GetData与SetData。

其中需要注意的问题有两点:

1.生成的目标纹理,规格需要与原始纹理相同。

这里的规格,其实也就是指Texture2D构造函数中的【int numberLevels, TextureUsage usage, SurfaceFormat format】三个参数。那么如何来解决这个问题呢?其实很简单,从原始纹理中获取这三个属性,传入目标纹理的构造函数中即可。这样一来,目标纹理与原始纹理规格绝对相同。

不知是否有人要问,原始纹理的规格你如何获得?呵~ 这个你自然不用管,因为有Xna的内容管线替你完成~

2.使用GetData从原始纹理获取数据时,各个参数的确定问题。

我们获取数据,一般要用到此方法的第三个重载方法,即:

public void GetData<T>(int level, Rectangle? rect, T[] data, int startIndex, int elementCount);

T模板,不用问,当然是通用性最强的byte。

第一个参数,一般置0即可。

第二个参数,当然就是你要截取的矩形区域,你自己生成的纹理,位置的对应当然得自己掌握。

第三个参数,根据T的设定,自然是byte[]类型的数据缓冲区。需要注意,GetData对这个缓冲区的长度有着严格的要求——不能大也不能小。那我们如何来获得这个缓冲区长度呢?这里我推荐一条定律:原始纹理使用Xna中通用性最强的.png,则其被内容管道编译为.xnb且加载至Texture2D之后,刚刚好每个像素占4个字节(r,g,b,α)。于是,假定你截取的区域为50*10,则数组长度必然为50*10*4=2000.

第四个参数,数组的起始索引,为充分利用数组空间,当然置0.

第五个参数,元素个数,当然等于byte[]缓冲区的长度了。

SetData参数用法类似。

原理代码如下:

/// <summary>
/// by kenkao(http://blog.csdn.net/kenkao)
/// </summary>
///
int StringWidth;          //字符串宽(目标纹理宽)
int StringHeight;         //字符串高(目标纹理高)
Texture2D SurTexture;     //原始纹理
Texture2D DesTexture;     //目标纹理
SurTexture = Content.Load<Texture2D>("Font");
DesTexture = new Texture2D(graphics.GraphicsDevice, StringWidth, StringHeight, SurTexture.LevelCount, SurTexture.TextureUsage, SurTexture.Format);//生成与原始纹理相同规格的目标纹理
byte[] data = new byte[StringWidth * StringHeight * 4];  //生成数据缓冲区
//SurTexture.GetData获取原始数据
//………………
//DesTexture.SetData赋值
//………………
//绘制DesTexture即可 

因为所有数据事先已经加载到内存之中,因此即使是即时生成新的目标纹理即时绘制,针对于人眼相对信息显示的感官要求而言,亦是绰绰有余的。

注意:提一个很外行的话题,千万不要试图从原始纹理中一个字一个字的截取出来,然后再一个字一个字的绘制上去。道理我不说,大家也应该懂。否则用上述方法就没什么意义了~

另,为进一步提高效率,我们应该避免反复的new、dispose(.net基本常识),大家可以提供一个缓存机制,即构建一个string到Texture2D的缓存映射即可。

如果你想知道有关Xna纹理字体的更多相关细节,以及如何自行生成一套Xna字体纹理,这里推荐几篇经典文章供大家参考:

>>> http://blogs.msdn.com/garykac/archive/2006/08/30/728521.aspx
 >>> http://blogs.msdn.com/garykac/articles/732007.aspx
 >>> http://www.angelcode.com/products/bmfont/

4.扩展content processor

此种方法是此次需要重点介绍的方法,也是笔者较为推荐的方法。

如下来自:

http://xna.omgsoft.com.cn/education/unicode_font_class.aspx (Xna游戏世界)

在XNA中显示中文字符或其它UNICODE字符(非GDI+)

XNA3.0+VS2008SP1下调试通过

由于XNA内置的DrawString方法并不能输出全角UNICODE字符,只能设定字符的起始和终止的内码,欧洲语系的字元不多,可以一次导入并生成字体,但像亚洲语系这样动辄上千的字元又是全角,好像设计者并没有考虑到这些情况。为了实现字符输出,已经有一些方法,例如利用.net中的GDI+。下面的实现方法是通过生成自定义的文字托管方式来实现的。

步骤如下:

建立字体文件
在当前项目中的“Content”中点击右键
加入新的文件,类型是"Sprite Font",起名为"DefaultFont.spritefont"
打开这个XML格式的文件,将"FontName"节中的字体改成含有目标语言字体的字体文件,这里使用“幼圆”
字典文件:
把游戏中需要的文字放到一个文本文件“message.txt”中,方便随时修改,以换行符结尾,内容如下: message.txt
中文输入测试,日本語テストを入力する

将这个文件放置在项目的Content目录下。
另存为一下这个文件,以“UTF-8”编码格式。
在解决方案浏览器中选择这个文件,在属性窗口的高级中的“生成操作”中选择“无”,“复制到输出目录”里选择“始终复制”。
文字处理类:
在解决方案浏览器中右键点击解决方案
添加新的项目,在项目类型对话框中选择"Windows Game Library(3.0)",起名"FontProcess"
在项目中增加引用,选择“Microsoft.Xna.Content.Pipeline”
将这个项目中的默认类"Class1.cs"改名为"DefaultFontProcessor.cs",修改为如下代码:
重新编译这个项目

DefaultFontProcessor.cs
using System.IO;
using Microsoft.Xna.Framework.Content.Pipeline;
using Microsoft.Xna.Framework.Content.Pipeline.Graphics;
using Microsoft.Xna.Framework.Content.Pipeline.Processors;
namespace FontProcessors
{
[ContentProcessor]
public class DefaultFontProcessor : FontDescriptionProcessor
{
public override SpriteFontContent Process(FontDescription input, ContentProcessorContext context)
{
//载入文件
string fullPath = Path.GetFullPath("message.txt");
context.AddDependency(fullPath);
string letters = File.ReadAllText(fullPath, System.Text.Encoding.UTF8);
//导入字符
foreach (char c in letters)
{
input.Characters.Add(c);
}
return base.Process(input, context);
}
}
}

添加项目引用
在本项目的Content下的"引用"上点击右键,添加项目引用,在弹出的对话框中选择刚才建立的项目:“FontProcessors”
在解决方案管理器选择本项目中的字体文件"DefaultFont.spritefont"
在属性窗口中的Content Processor中选择我们建立的处理类:"DefaultFontProssor"
在项目用使用
在我们的项目中使用如下代码:

Game1.cs
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;
namespace HelloWorld
{
public class GameMain : Microsoft.Xna.Framework.Game
{
private GraphicsDeviceManager graphics;
private SpriteBatch spriteBatch;
private SpriteFont font;
public GameMain()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
}
protected override void Initialize()
{
base.Initialize();
}
protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
font = Content.Load<SpriteFont>("DefaultFont");
}
protected override void UnloadContent()
{
}
protected override void Update(GameTime gameTime)
{
if (GamePad.GetState(PlayerIndex.One).Buttons.Back ==
ButtonState.Pressed)
{
Exit();
}
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
graphics.GraphicsDevice.Clear(Color.CornflowerBlue);
spriteBatch.Begin();
DrawString("中文输入测试,日本語テストを入力する", 50, 50);
spriteBatch.End();
base.Draw(gameTime);
}
private void DrawString(String str, int x, int y)
{
spriteBatch.DrawString(font, str, new Vector2(x, y), Color.White);
}
}
}

或可参考:http://blog.csdn.net/sweetwxh/archive/2008/03/20/2199762.aspx

http://hi.baidu.com/wingde%BF%D5%BC%E4/blog/item/107643541e404dceb745aec9.html

http://www.cnblogs.com/aawolf/archive/2010/09/22/1833167.html

http://www.cnblogs.com/kenshincui/archive/2011/04/10/2011695.html

Xna支持中文显示方法归纳相关推荐

  1. 让英文版的LINUX 支持中文显示

    (以REDHAT为例) 1.首先查看系统中有没有安装中文支持软件包   rpm -qa |grep fonts-chinese 如果命令执行后能够查询到相应的包,那么说明已经安装过包:反之则没有安装 ...

  2. atom编辑器Linux中文版,linux atom 怎么支持中文 Linux下Atom编辑器不支持中文解决方法...

    Atom 是 Github 专门为程序员推出的一个跨平台文本编辑器.具有简洁和直观的图形用户界面,并有很多有趣的特点:支持CSS,HTML,JavaScript等网页编程语言.它支持宏,自动完成分屏功 ...

  3. 让黑莓模拟器支持中文显示

    黑莓模拟器不支持中文显示和输入,调试中文程序的时候出现方块,解决方法如下: [首先找到模拟器安装目录] 情况一:如果使用的是bb jde for eclipse plugins的话,找到eclipse ...

  4. [django]Django站点admin支持中文显示和输入设置

    正文: Django站点admin支持中文输入设置,操作如下: 1 需要确定的你的数据库的client客户端和服务端的编码设置为utf-8,如果不是,请将其设置成utf-8编码,我采用mysql,详情 ...

  5. 一百零二、Hive——hive设置元数据支持中文显示

    在hive中建外部表时遇见到这样一个问题,就是表字段的中文注释在desc 表结构时看不了,发现原来是Hive的元数据库没有设置支持中文显示 第一步,在元数据库metastore完成初始化后,再次登录M ...

  6. svn自动邮件提醒(win7下支持中文显示,使用commit-emial.pl)

    1 前提:已安装svn,假设已有版本库名称为 :share 2 安装perl并重新启动.     下载并安装  ActivePerl-5.14.2.1402-MSWin32-x86-295342.ms ...

  7. QT嵌入式QT支持中文显示(zynq)

    @QT嵌入式QT支持中文显示 开发板可以使用文泉驿字体.在如下链接下载wqy-zenhei-0.8.38-1.tar.gz https://sourceforge.net/projects/wqy/f ...

  8. OpenCV文字绘制支持中文显示

    OPenCV版本:4.4 IDE:VS2019 功能描述 OpenCV绘制文本的函数putText()不支持中文的显示,网上很多方法推荐的都是使用FreeType来支持,FreeType是什么呢?Fr ...

  9. linux系统可以显示中文输入法,2 Linux支持中文显示和中文拼音输入法(番外篇)...

    今天打开虚拟机 linux  本来要整理笔记 发现Linux不支持中文.修改了/etc/sysconfig/i18n也不好使. 后来我猜想是没有装中文语言包,上网一查果然是这样. 装语言包: 1找到r ...

最新文章

  1. TinyMind邀你写诗!100小时GPU,等你来领取!
  2. 浪潮、寒武纪联手,目标:新基建智算中心
  3. Vertica的这些事lt;十二gt;—— vertica存储统计信息
  4. R语言ncol函数获取dataframe或者matrix列的个数实战
  5. JSON.stringify报cyclic object value错误
  6. [转载] 中华典故故事(孙刚)——24 嫁鸡随鸡_嫁狗随狗
  7. 解决a different object with the same identifier value was already associated with the session错误...
  8. 【观点】传统企业如何在数字化时代实现进化?
  9. linux怎么添加中文服务器,linux不支持中文怎么办_网站服务器运行维护
  10. php pos 接收,PHP开发中php pos()函数的使用详解
  11. [转载] numpy.gradient
  12. Uva220 Othello
  13. jade linux 安装教程,ROS-Jade版在UbuntuKylin15.04上的安装
  14. 使用 ActiveReports 报表工具,动态创建报表模板
  15. 超级记事本android,基于Android的超级记事本APP设计.doc
  16. 股票python量化交易014-计算收益率
  17. Unity - Timeline 之 Activation track properties(激活轨道的属性)
  18. Wed Sep 16 2020 00:00:00 GMT+0800 (中国标准时间)时间转换为mysql date类型
  19. 幽默的最高境界——这才叫幽默
  20. word无法打开请去应用商店_抖音去水印 | HTTP Catcher方法全解析

热门文章

  1. L1-02 聪明的高斯 (5 分)
  2. 如何学习嵌入式开发必备技能
  3. 那些年,我们解析过的前端异常
  4. Activity的Launch mode详解,A B C D的singleTask模式
  5. Saltstack远程执行命令(3)
  6. 【Computer Organization笔记23】非易失性存储:磁表面存储设备,磁盘的访问过程,RAID技术
  7. C语言 小游戏 电脑大概率获胜,用C语言实现简单的三子棋小游戏
  8. java swing 图片上加热点_外卖图片品牌全靠P,4元成本料理包加热后,平台上20元卖出...
  9. scala可变长度参数(一)
  10. 本地仓库的基本操作与概念——Git的学习与使用(三)