在XNA中,实现2D文本一般通过添加一个SpriteFont的文件,这个文件是XML格式的,用它可以来控制字符的样式大小等一些属性。
添加方法:
点击Content项目,右键——Add——New Item——选择spritefont。
添加后,默认中的内容如下:
Segoe UI Mono
14
0
true
Regular
 
~
在添加spritefont文件之后,既可以像其他资源一样,通过Content.Load方法来加载到游戏中,并显示在界面上。
//定义类级别变量
SpriteFont spritefont;
//在ContenLoad函数中加载资源
spritefont = Content.Load(@"Fonts\SpriteFont");
最后在Draw()方法中绘出即可。这样便可以显示一个文本了。
这是比较通用的做法。其好处就是简便快速。但是缺点也可以看出,在上面的XML中我们需要设置一个字符范围,对于只需要显示字母或一般的字符来说设为32到126确实够用了,但是如果我们要显示汉字,那就不好办了,因为汉字有几万个,我们虽然可以设置它的范围为几万,但是这样太耗资源,而且程序的执行速度和效率也比较低。不适合。所以我们采取另一种方式:通过Font Description Processor来处理。
第一步:
我们在其他位置新建一个txt文档,写上我们的中文字符,保存。
注意:这里保存的时候需要以UFT-8的格式保存。
接着我们将这个txt文件添加游戏Content的Fonts文件夹中。由于文件在Content项目中默认XNAGameFontContent中的文件都需要进行编译,编译时会自动检测里面的文件类型,而txt文件不属于这其中任何类型,因此我们需要修改它的BuildAction属性为None。
第二步:
我们点击解决方案,添加一个新的Project类型为Content Pipeline Extension Library(4.0).
这个时候的解决方案的视图如下:
第三步:
修改ContentProcessor.cs文件(文件名称如上图所示)
首先我们需要将ContentProcessor设置为继承至 FontDescriptionProcessor:
Public class ContentProcessor :FontDescriptionProcessor
{…………..}
接着需要重写FontDescriptionProcessor中的SpriteFontContent Process方法。
完整代码如下所示:
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content.Pipeline;
using Microsoft.Xna.Framework.Content.Pipeline.Graphics;
using Microsoft.Xna.Framework.Content.Pipeline.Processors;
// TODO: replace these with the processor input and output types.
using System.IO;
namespace ContentPipelineExtension
{
[ContentProcessor(DisplayName = "ContentPipelineExtension.ContentProcessor")]//这个名字用于SpriteFont的Conten Process属性
public class ContentProcessor :FontDescriptionProcessor
{
string txtFilePath = @"../SpriteFontDemoContent/Fonts/SpriteFont.txt";//这里由于.txt文件存在于不同的项目文件
//所以需要先退出当前项目在进入到.txt项目。
//重写基类中的SpriteFontContent Process方法
public override SpriteFontContent Process(FontDescription input, ContentProcessorContext context)
{
string path = Path.GetFullPath(txtFilePath);//获得.txt文件的完整路径
context.AddDependency(path);
string content = File.ReadAllText(path, System.Text.Encoding.UTF8);//注意在.txt保存的时候需要保存为UTF-8的格式,因而此处也许用UFT-8来读取
foreach (char c in content)
{
//将读取的字符存放到FontDescription中
input.Characters.Add(c);
}
return base.Process(input, context);
}
}
}
第四步:
点击游戏的Conten解决方案即:SpriteFontDemoContent,右键选择Project Dependencies,此时会弹出如下对话框:
选中SpriteFontDemo.勾选ContentPipelineExtension. 以此添加游戏项目对内容管道扩展的依赖。
第五步:
在Fonts的文件夹中再添加一个SpriteFont类型的文件,命名为SpriteChine,添加之后点击SpriteFontChinese.spritefont文件右键,选择properties.设置Conten Processor为ContentPipelineExtension,如下图所示
下面是SpriteFontChinese.spritefont文件的XML代码:
微软雅黑
24
0
true
Bold
~
以上的工作完成之后,我们便可以正式的写代码,来显示中文汉字了。
最后一步:
在Game1.cs中添加如下代码:
using System;
using System.Collections.Generic;
using System.Linq;
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.Input.Touch;
using Microsoft.Xna.Framework.Media;
namespace SpriteFontDemo
{
///
/// This is the main type for your game
///
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
SpriteFont spritefont;//英文文本
Vector2 sfPosition;//英文文本显示位置
SpriteFont spriteChineseFont;//中文文本
Vector2 scfPosition;//中文文本显示位置
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
graphics.PreferredBackBufferWidth = 480;
graphics.PreferredBackBufferHeight = 800;
// Frame rate is 30 fps by default for Windows Phone.
TargetElapsedTime = TimeSpan.FromTicks(333333);
// Extend battery life under lock.
InactiveSleepTime = TimeSpan.FromSeconds(1);
}
protected override void Initialize()
{
//初始化文本位置
sfPosition = new Vector2(130, 200);
scfPosition = new Vector2(160, 400);
base.Initialize();
}
///
/// LoadContent will be called once per game and is the place to load
/// all of your content.
///
protected override void LoadContent()
{
// Create a new SpriteBatch, which can be used to draw textures.
spriteBatch = new SpriteBatch(GraphicsDevice);
//加载文本资源
spritefont = Content.Load(@"Fonts/SpriteFont");
spriteChineseFont = Content.Load(@"Fonts/SpriteFontChinese");
}
///
/// UnloadContent will be called once per game and is the place to unload
/// all content.
///
protected override void UnloadContent()
{
}
///
/// Allows the game to run logic such as updating the world,
/// checking for collisions, gathering input, and playing audio.
///
/// Provides a snapshot of timing values.
protected override void Update(GameTime gameTime)
{
// Allows the game to exit
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
base.Update(gameTime);
}
///
/// This is called when the game should draw itself.
///
/// Provides a snapshot of timing values.
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
spriteBatch.Begin();
//绘制字母
spriteBatch.DrawString(spritefont, "English SpriteFont", sfPosition, Color.Black);
//绘制中文
spriteBatch.DrawString(spriteChineseFont, "中文字体", scfPosition, Color.Red);
spriteBatch.End();
base.Draw(gameTime);
}
}
}
由于以上的代码没有什么新鲜的东西,就不做过多的说明了,下面是运行效果视图:
|