XNAメモ – メニューの作り方

Posted: 2012年1月13日 カテゴリー: プログラミングメモ, XNA, XNAメモ
タグ:, , , , , , , ,

今回はメニューの作り方をメモります。今回は時間の都合から、2,3回に分けて書きます。

最初に、プロジェクトにSpritefontを一つ追加してください。その後は、メニューで使う変数を宣言します。今回使うのは、選択する為の文字列、タイトルとかに使うただ単に描画するだけの文字列、それらの文字列を描画する位置、現在選ばれている文字を指すint値、現在選ばれているオプションの文字列の色、選ばれてないオプションの色です。

class Menu
{
List<string> m_menuItem; //メニューのオプション
List<string> m_menuText; //ただの文字列
List<Vector2> m_positions; // オプションの位置
List<Vector2> m_textPosition; // 文字列の位置
Color m_selectedColour; // 選択されているオプションの色
Color m_unSelectedColour; // 選択されていないオプションの色
int m_currentMenuItem; // 現在選択されているオプション
 

宣言後は、コンストラクタで初期化します:


public Menu(Color selectedColour, Color unSelectedColour)
{
m_menuItem = new List<string>();
m_menuText = new List<string>();
m_positions = new List<Vector2>();
m_textPosition = new List<Vector2>();
m_selectedColour = selectedColour;
m_unSelectedColour = unSelectedColour;
m_currentMenuItem = 0;
}
 

次に、メニュー用のオプションや、文字列を足すメソッドを作ります。これは単に表示する文字列と、描画する位置を渡すだけです。


public virtual void AddMenuItem(string name, Vector2 position)
{
m_menuItem.Add(name);
m_positions.Add(position);
}

public void AddMenuText(string text, Vector2 position)
{
m_menuText.Add(text);
m_textPosition.Add(position);
}
 

作り終わったら、実際にメニュー用のオプションを足して見ます。


Menu menu;

public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";

menu = new Menu(Color.Gold, Color.White);

// メニューにオプションを足す
menu.AddMenuItem("Start", new Vector2(400.0f, 300.0f));
menu.AddMenuItem("Option", new Vector2(400.0f, 340.0f));
menu.AddMenuItem("Exit", new Vector2(400.0f, 380.0f));
}
 

今度は、メニューを描画処理を作ります。基本的にすることは、リスト内に保存されている、メニューのオプションを全て描画するだけです。その時、現在選ばれている(例えると、カーソルが乗っている文字)オプションだけ違う色にします。そうする事で、メニューの操作中に何処を選んでいるかわかり易くなります。


public virtual void Draw(SpriteBatch sp, SpriteFont font)
{
// メニューのオプションを描画する
for (int i = 0; i < m_menuItem.Count; i++)
{
// もし現在カーソルがあっている場合
if (i == m_currentMenuItem)
{
// 違う色で描画する
sp.DrawString(font, m_menuItem[i], m_positions[i], m_selectedColour);
}
else
{
// 他と同じ色で描画する
sp.DrawString(font, m_menuItem[i], m_positions[i], m_unSelectedColour);
}
}
 

ただの文字列の描画も、色を変える以外は同じようにします。描画が出来れば後はメニュー内で移動するだけです。そのためには、m_currentMenuItemの数を上げるか、下げる必要があります。移動した際には、メニューの上限を過ぎた場合最初に戻るようにします。


/// <summary>
/// 次のオプションへ移動する
/// </summary>
public virtual void SelectNext()
{
if (m_currentMenuItem < m_menuItem.Count - 1)
{
m_currentMenuItem++;
}
else
{
m_currentMenuItem = 0;
}
}

/// <summary>
/// 前のオプションへ移動する
/// </summary>
public virtual void SelectPrevious()
{
if (m_currentMenuItem > 0)
{
m_currentMenuItem--;
}
else
{
m_currentMenuItem = m_menuItem.Count - 1;
}
}
 

実装が終われば、後は実際に動かしてみます。


if (Input.IsPressed(Keys.Down))
{
// 下へ移動
menu.SelectNext();
}

if (Input.IsPressed(Keys.Up))
{
// 上へ移動
menu.SelectPrevious();
}
 

上のコードでは、Input.IsPressed()という、メソッドを使っていますが、これはキーが現在のフレームに押された場合だけ、trueを返します。そうしないと、メニューが一押しでかなり移動してしまうので、これを使っています。これ自体はメニューと関係ないのと、実装するのが簡単なので中身は記載しません。

メニューとして扱うには、メニューで何かが選択された時にどのオプションが選択されたかを知る必要が有るので、m_currentMenuItemへのアクセサを作ります。


public int SelectedNumber
{
get { return m_currentMenuItem; }
}
 

後は実際に選択された時にどうするかを実装するだけです。


// メニューで選択された場合
if (Input.IsPressed(Keys.Enter))
{
int option = menu.SelectedNumber;

if (option == 0)
{
// ...スタートが選択されたときの処理
}
else if (option == 1)
{
// ...Optionが選択されたときの処理
}
else if (option == 2)
{
// ...exitが選択されたときの処理
}
}
 

実装後はこんな感じになります(メニューを描画するのを忘れずに):

 

今回はココまでです。今回は凄く基本的な機能しか実装してないので、次回のメモを読んだり、実装方法こみで色々と試してみてください。

例を挙げると:

–       現在選択されているオプションの隣にアイコンの表示(次回書く予定)

–       選んでいる選択肢が大きくなり、移動すると元に戻る(次回かその次に書く予定)

–       メニューのオプションを一つのクラスとして扱ってみる

–       メニュークラス内で、移動等の処理の実装してみる

–       メニューの選択後の処理のif文に、intの代わりにenumを使う

–       CurrentNumberのアクセサの代わりに、string型や、enum型を返すようにする

今回紹介した実装方法や、上で例に挙げた方法は好みによる所が多いので、自分が使いやすいようにいじってみてください。

コメント
  1. araki より:

    メニューとして扱うには、メニューで何かが選択された時にどのオプションが選択されたかを知る必要が有るので、m_currentMenuItemへのアクセサを作ります。

    public int SelectedNumber
    {
    get { return m_currentMenuItem; }
    }

    ↑のコードはどこに記述すれば良いのでしょうか?
    初歩的な質問ですみません。

    • K1 より:

      アクセサの扱いは、クラス内のメソッド(関数)と同じなので、他のメソッド同様Menuクラスの内部に追加してください。

      具体的には、

      class Menu
      {
      // …. 変数宣言

      // …. コンストラクタ等

      public int SelectedNumber
      {
      get { return m_currentMenuItem; }
      }

      // …. 他のメソッド
      }

      の用にです。

コメントを残す