Наверняка, те кто заинтересовался созданием приложений с использованием XNA, столкнулись с проблемой вывода текста в кириллице. Дело в том, что XNA — инструмент, а не набор готовых средств и многие решения придется реализовывать самому. Как писалось в предыдущей статье XNA/XNA 3.0 – Быстрый старт для профи есть возможность создания своего контент процессора, чем мы и займемся.
Для начала создадим новый проект WindowsGameN. Думаю в картинках нет смысла показывать ).
Далее в дереве проекта добавим выбираем папку Content и добавляем новый объект SpriteFont1.spritefont, его можно открыть любым текстовым редакторов и внести изменения типа размер шрифта, наклон,… с этим разберетесь сами, ничего сложного простой xml файл.
Теперь создаем экземпляр класса SpriteFont на основе нашего SpriteFont1
Для начала создадим новый проект WindowsGameN. Думаю в картинках нет смысла показывать ).
Далее в дереве проекта добавим выбираем папку Content и добавляем новый объект SpriteFont1.spritefont, его можно открыть любым текстовым редакторов и внести изменения типа размер шрифта, наклон,… с этим разберетесь сами, ничего сложного простой xml файл.
Теперь создаем экземпляр класса SpriteFont на основе нашего SpriteFont1
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
SpriteFont m_SFont;
protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
m_SFont = Content.Load("SpriteFont1");
}
Если сейчас попробывать что-либо написать с использованием кириллицы то увидим ошибку.

Собственно, устранение которой мы займемся) Добавляем к имеющемуся солюшену новый проекту WindowsGameLibrary1.
Добавляем класс ContentProcessor1 и переписываем подобным образом:
using System;
using System.Collections.Generic;
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;
using TInput = System.String;
using TOutput = System.String;
using System.ComponentModel;
using System.IO;
namespace WindowsGameLibrary1
{
[ContentProcessor(DisplayName = "MyCharacterSetFontProcessor")]
public class Class1 : FontDescriptionProcessor
{
public override SpriteFontContent Process(FontDescription input, ContentProcessorContext context)
{
string fullPath = Path.GetFullPath(MessageFile);
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);
}
[DefaultValue("messages.txt")]
[DisplayName("Message File")]
[Description("Файл с символами которые будут автоматически добавлены в шрифте.")]
public string MessageFile
{
get { return messageFile; }
set { messageFile = value; }
}
private string messageFile = "..\\messages.txt";
}
}
В файле messages.txt содержатся нужные нам символы. Вкратце, мы читаем символы из файла и добавляем их в текущий процессор шрифта.
В файле могут содержаться как набор символов так и строки с фразами которые планируется выводить, повторяющиеся символы автоматически будут проигнорированы.
Мой файл выглядит так
йцукенгшщзхъэждлорпавыфячсмитьбюЙЦУКЕНГШЩЗХЪЭЖДЛОРПАВЫФЯЧСМИТЬБЮ
после этого нужно добавить зависимость проекта от библиотеки, для этого выбираем в дереве наш WindowsGameN, в контекстном меню выбираем Project Dependencies... и указываем зависимость от WindowsGameLibrary1

Добавляем референс на библиотеку.
Выбираем наш SpriteFont1.spritefont и в свойстве Content Processor выбираем наш MyCharacterSetFontProcessor.
Вот и все.
Далее тест:
protected override void Draw(GameTime gameTime)
{
graphics.GraphicsDevice.Clear(Color.CornflowerBlue);
string message = "Все работает!";
Vector2 viewportSize = new Vector2(GraphicsDevice.Viewport.Width,
GraphicsDevice.Viewport.Height);
Vector2 textSize = m_sFont.MeasureString(message);
Vector2 textPosition = (viewportSize - textSize) / 2;
spriteBatch.Begin();
spriteBatch.DrawString(m_sFont, message, textPosition, Color.Black);
spriteBatch.End();
base.Draw(gameTime);
}
Вот и все, классы и проекты назвать ттолько нужно по человечески)