在XNA中,实现2D文本一般通过添加一个SpriteFont的文件,这个文件是XML格式的,用它可以来控制字符的样式大小等一些属性。
添加方法:
点击Content项目,右键——Add——New Item——选择spritefont。
添加后,默认中的内容如下:
<?xml version="1.0" encoding="utf-8"?> <XnaContent xmlns:Graphics="Microsoft.Xna.Framework.Content.Pipeline.Graphics"> <Asset Type="Graphics:FontDescription"> <FontName>Segoe UI Mono</FontName><!--字体类型--> <Size>14</Size><!--字体大小--> <Spacing>0</Spacing><!--字体间距--> <UseKerning>true</UseKerning><!--字体布局--> <Style>Regular</Style><!--字体样式,如加粗,斜体等--> <CharacterRegions> <!--字体区间,表示示字符的范围,例如在此设置32到126,则为只显示ASCII字符--> <CharacterRegion> <Start> </Start> <End>~</End> </CharacterRegion> </CharacterRegions> </Asset> </XnaContent>
在添加spritefont文件之后,既可以像其他资源一样,通过Content.Load方法来加载到游戏中,并显示在界面上。
//定义类级别变量 SpriteFont spritefont; //在ContenLoad函数中加载资源 spritefont = Content.Load<SpriteFont>(@"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代码:
<?xml version="1.0" encoding="utf-8"?> <XnaContent xmlns:Graphics="Microsoft.Xna.Framework.Content.Pipeline.Graphics"> <Asset Type="Graphics:FontDescription"> <FontName>微软雅黑</FontName> <Size>24</Size> <Spacing>0</Spacing> <UseKerning>true</UseKerning> <Style>Bold</Style> <CharacterRegions> <CharacterRegion> <Start> </Start> <!—注意这里要添加一个空格--> <End>~</End> <!—这里用 ~ 符号--> </CharacterRegion> </CharacterRegions> </Asset> </XnaContent>
以上的工作完成之后,我们便可以正式的写代码,来显示中文汉字了。
最后一步:
在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 { /// <summary> /// This is the main type for your game /// </summary> 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(); } /// <summary> /// LoadContent will be called once per game and is the place to load /// all of your content. /// </summary> protected override void LoadContent() { // Create a new SpriteBatch, which can be used to draw textures. spriteBatch = new SpriteBatch(GraphicsDevice); //加载文本资源 spritefont = Content.Load<SpriteFont>(@"Fonts/SpriteFont"); spriteChineseFont = Content.Load<SpriteFont>(@"Fonts/SpriteFontChinese"); } /// <summary> /// UnloadContent will be called once per game and is the place to unload /// all content. /// </summary> protected override void UnloadContent() { } /// <summary> /// Allows the game to run logic such as updating the world, /// checking for collisions, gathering input, and playing audio. /// </summary> /// <param name="gameTime">Provides a snapshot of timing values.</param> 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); } /// <summary> /// This is called when the game should draw itself. /// </summary> /// <param name="gameTime">Provides a snapshot of timing values.</param> 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); } } }
由于以上的代码没有什么新鲜的东西,就不做过多的说明了,下面是运行效果视图:
转载于:https://blog.51cto.com/potential/1402563