WisdomSoft - for your serial experiences.

キーボード

キーボードの状態を取得し、キーが押されているかどうかを調べます。押されているキーだけを取得することも可能です。

キーの状態を得る

XNA Framework ゲームは、キーボードの状態を取得することができます。USB キーボードであれば、Xbox 360 でも PC でも、同じように使うことができます。Xbox 360 では、キーボードがゲームに使われることは滅多にありませんが、タイピングゲームのようなキー入力テクニックをゲーム要素に取り入れる場合には有効でしょう。Windows PC 用のゲームの場合、コントローラの代わりにキーボードが使われるのは一般的です。

キーボードの状態を取得する方法は、コントローラの状態を取得する方法と構造的に同じです。まず最初に、キーボードの状態を提供する Microsoft.Xna.Framework.Input.Keyboard クラスを使います。

Microsoft.Xna.Framework.Input.Keyboard クラス
public static class Keyboard

このクラスは、キーボードの現在の状態を返す静的な GetStaet() メソッドを提供します。

Keyboard クラス GetState() メソッド
public static KeyboardState GetState ()
public static KeyboardState GetState (
         PlayerIndex playerIndex
)

パラメータを指定しない場合は、USB で接続されているキーボードの状態を返します。これに対して playerIndex パラメータを指定する場合は、指定したプレイヤー番号に対応するコントローラに接続された Chatpad の状態を返します。Chatpad は、Xbox 360 コントローラと組み合わせて使える小型のキーボードです。メソッドは、指定されたキーボードの状態を表す Microsoft.Xna.Framework.Input.KeyboardState 構造体の値を返します。

Microsoft.Xna.Framework.Input.KeyboardState 構造体
public struct KeyboardState

キーボードのボタンは 100 を超えるので、コントローラのようにボタンごとのプロパティがあるのではなく、個々のボタンの状態は KeyboardState 構造体のインデクサから取得できます。

KeyboardState 構造体のインデクサ
public KeyState this [
         Keys key
] { get; }

key パラメータには、キーボードのキーを表す Microsoft.Xna.Framework.Input.Keys 列挙型のメンバを指定します。インデクサは、指定されたキーの状態を返すという仕組みです。

Microsoft.Xna.Framework.Input.Keys 列挙型
public enum Keys

Keys 列挙型のメンバは、キーボードの各ボタンの名前に対応しています。文字キーであれば、そのままのアルファベットが使われています。例えば、A キーは A メンバで表されます。他のキーも、ボタンの名前がそのままメンバ名になっています。Enter キーであれば Enter メンバ、Esc キーであれば Escape メンバとなります。

インデクサは、パラメータに指定されたキーの状態を表す Microsoft.Xna.Framework.Input.KeyState 列挙型の値を返します。 

Microsoft.Xna.Framework.Input.KeyState 列挙型
public enum KeyState

キーの状態は、キーが押されているか、離されているかの 2 つしかありません。この列挙型は、押されている状態を表す Down メンバと、離されている状態を表す Up メンバを宣言しています。

キーが押されているかどうかは、IsKeyUp() メソッドと IsKeyDown() メソッドから調べられます。 

KeyboardState 構造体 IsKeyUp() メソッド
public bool IsKeyUp (Keys key)
KeyboardState 構造体 IsKeyDown() メソッド
public bool IsKeyDown (Keys key)

key パラメータには状態を調べたいキーを指定します。IsKeyUp() メソッドは、指定したキーが押されていなければ true を、そうでなければ false を返します。逆に IsKeyDown() メソッドはキーが押されていれば true を、そうでなければ false を返します。

コード1
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

public class TestGame : Game
{
    public static void Main(string[] args)
    {
        using (Game game = new TestGame()) game.Run();
    }

    private GraphicsDeviceManager graphicsDeviceManager;
    private SpriteBatch sprite;
    private Texture2D texture;
    private Vector2 position;

    public TestGame()
    {
        graphicsDeviceManager = new GraphicsDeviceManager(this);
        Content.RootDirectory = "Content";
    }

    protected override void LoadContent()
    {
        sprite = new SpriteBatch(GraphicsDevice);
        texture = Content.Load<Texture2D>("TestImage");
        base.LoadContent();
    }

    protected override void Update(GameTime gameTime)
    {
        KeyboardState state = Keyboard.GetState();

        string text = "";
        if (state[Keys.Up] == KeyState.Down)
        {
            position.Y += -2;
            text += "Up, ";
        }
        if (state[Keys.Down] == KeyState.Down)
        {
            position.Y += 2;
            text += "Down, ";
        }
        if (state[Keys.Left] == KeyState.Down)
        {
            position.X += -2;
            text += "Left, ";
        }
        if (state[Keys.Right] == KeyState.Down)
        {
            position.X += 2;
            text += "Right, ";
        }

        Window.Title = text;

        base.Update(gameTime);
    }

    protected override void Draw(GameTime gameTime)
    {
        GraphicsDevice.Clear(Color.White);

        sprite.Begin();
        sprite.Draw(texture, position, Color.White);
        sprite.End();

        base.Draw(gameTime);
    }
}
実行結果

コード1はキーボードの方向キーが押されていかどうかを調べ、押されている場合は position フィールドの値を更新してスプライトが描画される座標を移動します。

押されているキーだけを得る

方向キーが押されていればキャラクターを動かすなど、特定のキーの状態だけを調べるならば、インデクサや IsKeyUp() メソッドなどが有効ですが、文字キーの入力を処理するような場合は、すべての文字キーの状態を調べなければならず、現実的な方法ではありません。タイピングゲームの場合、文字キーの状態を順に調べるよりも、押されているキーだけを取得した方が効率的です。

現在押されているキーを取得するには GetPressedKeys() メソッドを使います。 

KeyboardState 構造体 GetPressedKeys() メソッド
public Keys[] GetPressedKeys ()

このメソッドは、状態が KeyState.Down のキーを表す Keys 列挙型の配列を返します。

コード2
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

public class TestGame : Game
{
    public static void Main(string[] args)
    {
        using (Game game = new TestGame()) game.Run();
    }

    private GraphicsDeviceManager graphicsDeviceManager;
    private SpriteBatch sprite;
    private SpriteFont font;
    private string text;

    public TestGame()
    {
        graphicsDeviceManager = new GraphicsDeviceManager(this);
        Content.RootDirectory = "Content";
    }

    protected override void LoadContent()
    {
        sprite = new SpriteBatch(GraphicsDevice);
        font = Content.Load<SpriteFont>("TestFont");
        base.LoadContent();
    }

    protected override void Update(GameTime gameTime)
    {
        KeyboardState state = Keyboard.GetState();
        Keys[] keys = state.GetPressedKeys();

        text = "";
        foreach (Keys key in keys)
        {
            text += key.ToString() + "\n";
        }

        base.Update(gameTime);
    }

    protected override void Draw(GameTime gameTime)
    {
        GraphicsDevice.Clear(Color.White);

        sprite.Begin();
        sprite.DrawString(font, text, Vector2.Zero, Color.Black);
        sprite.End();

        base.Draw(gameTime);
    }
}
実行結果
コード2 実行結果

コード2は、現在押されているキーの配列を取得し、これをテキストで画面上に表示するプログラムです。Draw() メソッド内では text フィールドの文字列をテキストとして描画しているだけです。このテキストは Update() メソッドで、キーの状態に従って更新されます。Update() メソッドでは、KeyboardState 構造体の GetPressedKeys() メソッドが返した Kyes 列挙型の配列を foreach 文で順に処理し、text フィールドに加えています。