9.3 メッセージ
9.3.1 テキストメッセージの表示
ゲーム中に、プレイヤーに何らかの警告やエラーなどのメッセージを表示する必要が発生した場合、ゲーム内でダイアログを描画するというのも 1 つの方法ですが、システムのメッセージボックスを利用する方法も用意されています。
ゲーマーサービスを利用している場合、ゲームは Guide クラスを通してシステムのメッセージボックスを表示することができます。ゲームがフォントを持たない場合などで、簡易メッセージとしてテキストを表示する手段として利用できます。
メッセージボックスを表示するには BeginShowMessageBox() メソッドを使います。
public static IAsyncResult BeginShowMessageBox ( PlayerIndex player, string title, string text, IEnumerable<string> buttons, int focusButton, MessageBoxIcon icon, AsyncCallback callback, Object state )
player パラメータには、このメッセージボックスを表示する対象のプレイヤーを指定します。title パラメータには、メッセージボックスのタイトルを、text パラメータには、メッセージボックスに表示するテキストの本文を指定します。buttons パラメータには、メッセージボックスに表示されるボタンのテキストを指定します。ボタンは、このパラメータに指定された列挙子の要素数に従って表示されます。このパラメータに指定できる要素数は、最大で 3 つまでです。focusButton パラメータには、デフォルトで選択されているボタンをインデックスで指定します。
icon パラメータには、メッセージボックスに表示されるアイコンを表す Microsoft.Xna.Framework.GamerServices.MessageBoxIcon 列挙型のいずれかのメンバを指定します。
public enum MessageBoxIcon
この列挙型には、アイコンを表示しないことを表す None メンバ、警告アイコンを表示することを表す Warning メンバ、エラーアイコンを表示することを表す Error メンバ、そして通知アイコンを表示することを表す Alert メンバが定義されています。
callback パラメータには、このメソッドの非同期処理が終了したタイミング、すなわちメッセージボックスが閉じられたタイミングで呼び出される AsyncCallback デリゲートを指定します。state パラメータには、この非同期処理を識別するための任意のオブジェクトを設定できます。最後に BeginShowMessageBox() メソッドは、非同期処理の状態を提供する IAsyncResult オブジェクトを返します。
プレイヤーは、メッセージボックスに選択されたボタンを選択してメッセージボックスを閉じることができますが、BeginShowMessageBox() メソッドの処理は非同期に行われます。プレイヤーがメッセージボックスのボタンを選択することを待つことなく、すぐに制御を返します。よって、Update() メソッドなどでメッセージボックスを呼び出しても、ゲーム自体が止まってしまうことはありません。
最初に、プレイヤーがどのボタンを選択したかという情報は受け取る必要のない、1 つの「OK」ボタンだけを持つメッセージボックスを作成してみましょう。非同期の操作が不要の場合 callback パラメータや state パラメータには null を指定できます。
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 graphicsDeviceManager; public Test() { graphicsDeviceManager = 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", "通知メッセージ", new string[] { "OK" }, 0, MessageBoxIcon.Alert, null, null ); else if (state.Buttons.B == ButtonState.Pressed) Guide.BeginShowMessageBox( PlayerIndex.One, "Error", "エラーメッセージ", new string[] { "OK" }, 0, MessageBoxIcon.Error, null, null ); else if (state.Buttons.X == ButtonState.Pressed) Guide.BeginShowMessageBox( PlayerIndex.One, "None", "アイコンのないメッセージ", new string[] { "OK" }, 0, MessageBoxIcon.None, null, null ); else if (state.Buttons.Y == ButtonState.Pressed) Guide.BeginShowMessageBox( PlayerIndex.One, "Warning", "警告メッセージ", new string[] { "OK" }, 0, MessageBoxIcon.Warning, null, null ); } base.Update(gameTime); } protected override void Draw(GameTime gameTime) { GraphicsDevice.Clear(Color.White); base.Draw(gameTime); } }
コード1は、コントローラの A、B、X、Y ボタンのいずれかを押すと、そのボタンに対応したアイコンのメッセージボックスを表示します。MessageBoxIcon 列挙型の値に従って、メッセージボックス上に適切なアイコンが表示されていることが確認できます。
9.3.2 選択結果を得る
BeginShowMessageBox() メソッドは、プレイヤーがメッセージボックスを閉じることを待たずに制御を返します。よって、プレイヤーが選択したメッセージボックスのボタンを得るには EndShowMessageBox() メソッドを呼び出します。
public static Nullable<int> EndShowMessageBox ( IAsyncResult result )
result パラメータには、BeginShowMessageBox() メソッドが返した IAsyncResult オブジェクトを指定します。このメソッドは、選択されたボタンのインデックスを返します。キャンセルによってメッセージボックスが閉じられると null を返します。
ただし、EndShowMessageBox() を呼び出すときは、メッセージボックスが閉じられた後でなければなりません。EndShowMessageBox() メソッドは、result パラメータに渡された非同期処理が終了していない場合、処理が終了するのを待機します。これを避けるには、BeginShowMessageBox() メソッドの callback パラメータに AsyncCallback デリゲートを設定します。このデリゲートは、メッセージボックスが閉じられたタイミングで呼び出されるため、ここで EndShowMessageBox() メソッドを呼び出します。
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 graphicsDeviceManager; private Color color; public Test() { graphicsDeviceManager = new GraphicsDeviceManager(this); Components.Add(new GamerServicesComponent(this)); color = Color.White; } private void CallbackShowMessageBox(IAsyncResult ar) { int? result = Guide.EndShowMessageBox(ar); if (result != null) { if (result == 0) color = Color.Red; else if (result == 1) color = Color.Lime; else if (result == 2) color = Color.Blue; } } 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, "背景の選択", "背景色を変更します。選択してください。", new string[] { "赤", "緑", "青" }, 0, MessageBoxIcon.None, CallbackShowMessageBox, null ); } base.Update(gameTime); } protected override void Draw(GameTime gameTime) { GraphicsDevice.Clear(color); base.Draw(gameTime); } }
コード2は、A ボタンを押すと「赤」「緑」「青」の 3 つのボタンが表示されたメッセージボックスが表示されます。このうち、いずれかのボタンが選択されると画面の背景色を指定された色に変更します。メッセージボックスが閉じられると CallbackShowMessageBox() メソッドが呼び出されるので、パラメータに渡された IAsyncResult オブジェクトを EndShowMessageBox() メソッドに渡します。メソッドは、この非同期処理の結果として選択されたボタンのインデックスを返します。