XNA Framework ゲームでは、システムのフォントを使えないため、フォントは意外と厄介な問題となります。特に XNA Framework 2.0
以降は、ネットワーク機能が搭載されたため、コンパイル時にゲームで使われる文字を確定できなくなることもあるでしょう。日本語のようなマルチバイト文字が含まれる場合、すべての文字を用意するとフォントでゲームサイズが肥大化します。加えて、フォントの権利問題もあります。一般に配布するゲームでは、再配布可能なフォントが必要になります。
こうした問題の解決にはなりませんが、ゲーム内で描画するのではなく、プレイヤーに通知するメッセージを表示したい場合は、システムが提供するメッセージボックスを使えます。メッセージボックスは、システムのフォントでテキストが表示されるため、システムが日本語に対応している場合、正しく日本語を表示してくれます。Xbox
360 で実行すると、メッセージを含むブレードが表示されます。Windows PC で実行すると、ガイド画面上にメッセージが表示されます。
メッセージボックスを表示するには、Guide クラスの静的な BeginShowMessageBox()
メソッドを使います。このメソッドは、パラメータに指定された文字列をメッセージボックスとして表示してくれます。システム画面に切り替わるため、ゲーム内で使うことはできませんが、ゲーム中に発生した警告やエラー処理に使うことができます。
■ Guide クラス BeginShowMessageBox() メッセージ
public static IAsyncResult BeginShowMessageBox (
PlayerIndex player,
string title,
string text,
IEnumerable<string> buttons,
int focusButton,
MessageBoxIcon icon,
AsyncCallback callback,
Object state
)
player パラメータには、このメッセージボックスと関連付けるプレイヤーを指定します。Windows PC の場合は、常に
PlayerIndex.One を指定します。それ以外のプレイヤーを指定した場合は例外が発生します。title
パラメータにはメッセージのタイトルを表示します。主に、メッセージボックスの上部に表示されます。text パラメータに、メッセージとして表示する本文を指定します。
メッセージボックス内には、最大で 3 つまでの任意のボタンを表示できます。buttons
パラメータには、メッセージボックス上に表示するボタンのテキストを表した文字列の列挙子を指定します。IEnumerable<string>
を実装するオブジェクトであれば何でもかまいませんが、文字列の配列が簡単です。focusButton
パラメータには、メッセージボックスが表示された時点で、最初にフォーカスを持っているボタンのインデックスを指定します。このインデックスは buttons
に指定した列挙子に対応します。
icon パラメータには、メッセージボックスに表示するアイコンの種類を表す Microsoft.Xna.Framework.GamerServices.MessageBoxIcon
列挙体のいずれかのメンバを指定します。
■ Microsoft.Xna.Framework.GamerServices.MessageBoxIcon 列挙体
public enum MessageBoxIcon
この列挙体には、注意や通知を表す Alert、警告を表す Warning、エラーを表す Error、アイコンを表示しないことを表す None
メンバが定義されています。メッセージボックスの外観や振る舞いはシステムによって異なりますが、意味に従った適切なアイコンがメッセージボックス内に表示されます。
最後の callback と state パラメータは、非同期操作のためのパラメータです。BeginShowMessageBox()
メソッドは非同期メソッドです。メッセージボックスが閉じられるのを待たずに、即座に制御を返します。callback
パラメータに指定したデリゲートは、メッセージボックスが閉じられた時に呼び出されます。state
には、非同期操作で使用する任意のユーザー定義データを指定できます。"OK"
ボタンしか持たない単純な通知用のメッセージボックスを表示するような場合であれば、特に不要なので null を指定できます。
メソッドの結果も、非同期操作で使われる IAsyncResult
オブジェクトです。選択されたボタンを取得するために使われますが、まずは単純なメッセージボックスを表示してみましょう。
■ Sample01
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.GamerServices;
public class Test : Game
{
public static void Main(string[] args)
{
using (Game game = new Test()) game.Run();
}
private GraphicsDeviceManager graphics;
private readonly string[] BUTTONS = new string[] { "OK" };
public Test()
{
graphics = new GraphicsDeviceManager(this);
Components.Add(new GamerServicesComponent(this));
}
protected override void Update(GameTime gameTime)
{
GamePadState state = GamePad.GetState(PlayerIndex.One);
if (!Guide.IsVisible)
{
if (state.Buttons.A == ButtonState.Pressed)
Guide.BeginShowMessageBox(
PlayerIndex.One, "Alert", "通知メッセージです。",
BUTTONS, 0, MessageBoxIcon.Alert, null, null
);
else if (state.Buttons.B == ButtonState.Pressed)
Guide.BeginShowMessageBox(
PlayerIndex.One, "Error", "エラーメッセージです。",
BUTTONS, 0, MessageBoxIcon.Error, null, null
);
else if (state.Buttons.Y == ButtonState.Pressed)
Guide.BeginShowMessageBox(
PlayerIndex.One, "Warning", "警告メッセージです。",
BUTTONS, 0, MessageBoxIcon.Warning, null, null
);
else if (state.Buttons.X == ButtonState.Pressed)
Guide.BeginShowMessageBox(PlayerIndex.One, "None", "通常のメッセージです。",
BUTTONS, 0, MessageBoxIcon.None, null, null
);
}
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.White);
base.Draw(gameTime);
}
}
■ 実行結果

Sample01 は、各アイコンを使ったメッセージボックスを表示するプログラムです。A ボタンを押すと Alert、B ボタンを押すと Error、Y
ボタンを押すと Warning、X ボタンを押すとアイコンを持たないメッセージボックスが表示されます。
複数のボタンを表示し、どのボタンが選択されてメッセージボックスが閉じられたのかを知るには EndShowMessageBox()
メソッドを使います。このメソッドは、BeginShowMessageBox() メソッドに対応しています。
■ Guide クラス EndShowMessageBox() メソッド
public static Nullable<int> EndShowMessageBox (
IAsyncResult result
)
result パラメータには BeginShowMessageBox() メソッドが返した IAsyncResult
オブジェクトを渡します。メソッドは、メッセージボックスで選択されたボタンのインデックスを表す null 可能整数型 int?
を返します。メッセージボックスがボタンの選択ではなく B ボタンによる戻るで閉じられた場合は null が返されます。
■ Sample02
using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.GamerServices;
public class Test : Game
{
public static void Main(string[] args)
{
using (Game game = new Test()) game.Run();
}
private GraphicsDeviceManager graphics;
private int? messageBoxResult;
public Test()
{
graphics = new GraphicsDeviceManager(this);
Components.Add(new GamerServicesComponent(this));
}
private void CallbackShowMessageBox(IAsyncResult ar)
{
messageBoxResult = Guide.EndShowMessageBox(ar);
}
protected override void Update(GameTime gameTime)
{
GamePadState state = GamePad.GetState(PlayerIndex.One);
if (!Guide.IsVisible)
{
string[] buttons1 = new string[] { "はい", "いいえ", "キャンセル" };
string[] buttons2 = new string[] { "OK" };
if (state.Buttons.A == ButtonState.Pressed)
{
Guide.BeginShowMessageBox(
PlayerIndex.One, "確認", "いずれかのボタンを選択してください。",
buttons1, 0, MessageBoxIcon.None, CallbackShowMessageBox, null
);
}
else if (messageBoxResult != null)
{
Guide.BeginShowMessageBox(
PlayerIndex.One, "結果", "「" + buttons1[messageBoxResult.Value] + "」ボタンが押されました",
buttons2, 0, MessageBoxIcon.None, null, null
);
messageBoxResult = null;
}
}
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.White);
base.Draw(gameTime);
}
}
■ 実行結果

Sample02 は、A ボタンを押すと「はい」、「いいえ」、「キャンセル」の 3 つのボタンを持つメッセージボックスを表示します。ボタンが選択されると CallbackShowMessageBox()
メソッドが呼び出されます。この中で EndShowMessageBox() メソッドを使って選択されたボタンのインデックスを messageBoxResult
フィールドに保存しています。その後、Update() メソッドで選択されたボタンをメッセージボックスのテキストとして表示します。ボタンを選択しなかった場合は
null が返されるので、その後のメッセージボックスは表示されません。
キーボード入力ダイアログ
Keyboard クラスから得られる KeyboardState
構造体の値から、現在のキーボードの状態を取得することは可能でした。しかし、この機能だけでは、プレイヤーに任意のテキストを入力してもらうことはできません。ゲーム開始時にキャラクターの名前を入力してもらうなどの処理を行うには、キー入力に合わせてテキストが正しく表示され、編集できなければなりません。こうした一連の作業を行うには、システムが用意しているキーボード入力ダイアログを使うと便利です。
キーボード入力ダイアログを表示するには Guide クラスの BeginShowKeyboardInput()
メソッドを使います。名前から想像できるように、このクラスも BeginShowMessageBox()
メソッドと同様に非同期メソッドです。テキストの入力を待たずに、すぐに制御を返します。
■ Guide クラス BeginShowKeyboardInput() メソッド
public static IAsyncResult BeginShowKeyboardInput (
PlayerIndex player,
string title,
string description,
string defaultText,
AsyncCallback callback,
Object state
)
player パラメータには、この入力を行うプレイヤーの PlayerIndex を指定します。Windows PC
上で実行するゲームの場合、有効なメンバは常に One のみです。title パラメータには、表示する入力ボックスのタイトルとなる文字列を、description パラメータには入力内容を指示する説明文などを表す文字列を、defaultText パラメータには、入力内容に表示されるデフォルトの文字列を指定します。
callback と state パラメータは、非同期操作に使われます。キーボード入力が終了した時点で callback
パラメータに指定したデリゲートが呼び出されます。state には、任意のユーザー定義データを指定できます。メソッドは、非同期操作の進捗などを表す IAsyncResult
オブジェクトを返します。
入力されたテキストを取得するには、BeginShowKeyboardInput () メソッドに対応する EndShowKeyboardInput()
メソッドを呼び出します。
■ Guide クラス EndShowKeyboardInput() メソッド
public static string EndShowKeyboardInput (
IAsyncResult result
)
result パラメータには、BeginShowKeyboardInput() メソッドが返したオブジェクトを指定します。メソッドは、プレイヤーが入力した文字列を返します。
Windows PC 上で実行した場合、キー入力に対応していますが IME に対応していないため日本語入力ができません。しかし、Xbox 360
上で実行した場合は、システムの仮想キーボードが表示されるため、日本語の入力も可能です。そのため、入力されたテキストをフォントで描画する場合は、予期せぬ文字が入力されている可能性があるので注意が必要です。
■ Sample03
using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.GamerServices;
public class Test : Game
{
public static void Main(string[] args)
{
using (Game game = new Test()) game.Run();
}
private GraphicsDeviceManager graphics;
private string keyboardInputResult;
public Test()
{
graphics = new GraphicsDeviceManager(this);
Components.Add(new GamerServicesComponent(this));
}
private void CallbackShowKeyboardInput(IAsyncResult ar)
{
keyboardInputResult = Guide.EndShowKeyboardInput(ar);
}
protected override void Update(GameTime gameTime)
{
GamePadState state = GamePad.GetState(PlayerIndex.One);
if (!Guide.IsVisible)
{
string[] buttons = new string[] { "OK" };
if (state.Buttons.A == ButtonState.Pressed)
{
Guide.BeginShowKeyboardInput(PlayerIndex.One, "入力テスト",
"任意のテキストを入力してください。",
"your world. your game.",
CallbackShowKeyboardInput, null
);
}
else if (keyboardInputResult != null)
{
Guide.BeginShowMessageBox(
PlayerIndex.One, "入力結果",
"入力されたテキストは\"" + keyboardInputResult + "\"です。",
buttons, 0, MessageBoxIcon.None, null, null
);
keyboardInputResult = null;
}
}
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.White);
base.Draw(gameTime);
}
}
■ 実行結果

Sample03 を実行して A ボタンを押すとキーボード入力ダイアログが表示されます。入力テキストには、デフォルトで "your world.your
game." が入力されていますが、キーボードからの入力で自由に編集することができます。Xbox 360
の場合は、画面上に仮想キーボードが表示されるため、コントローラからでも編集が可能です。送信ボタンを押すとダイアログが閉じられ、CallbackShowKeyboardInput()
メソッドが呼び出されます。ここで EndShowKeyboardInput() メソッドを呼び出して入力された文字列を取得しています。