WisdomSoft - for your serial experiences.

マウス

マウスカーソルの位置や、マウスボタンの状態を取得します。

カーソルの座標

マウスは、Xbox 360 プラットフォームではサポートされないため、Windows PC 用のゲームプロジェクトでのみ使うことができます。PC ユーザーの多くは、マウスとキーボードを使った操作に慣れているため、コントローラに対応する場合でも、マウスとキーボードでプレイしたいというプレイヤーのためにマウス入力にも対応するべきでしょう。

マウス入力もまた、コントローラやキーボードの状態を取得する方法と同じです。現在のマウスの状態を取得し、その値によって入力を確認します。マウスから、最大で 5 つのボタンの状態と、カーソルの座標を取得できます。

マウスの状態を得るには Microsoft.Xna.Framework.Input.Mouse クラスを使います。

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

現在のマウスの状態は、Mouse クラスの GetState() メソッドから取得できます。システムに接続されているマウスは常に 1 つだけなので、識別する必要はありません。

Mouse クラス GetState() メソッド
public static MouseState GetState ()

このメソッドは、マウスの状態を表す Microsoft.Xna.Framework.Input.MouseState 構造体の値を返します。

Microsoft.Xna.Framework.Input.MouseState 構造体
[SerializableAttribute]
public struct MouseState

マウスカーソルの座標は、MouseState 構造体の X プロパティから X 軸の座標を、Y プロパティから Y 軸の座標を、それぞれクライアント座標で取得できます。

MouseState 構造体 X プロパティ
public int X { get; }
MouseState 構造体 Y プロパティ
public int Y { get; }

これらのプロパティが返す X 座標と Y 座標は、ゲーム画面の左上隅を原点(0, 0)としたピクセル単位のクライアント座標です。取得した座標上に、何らかのスプライトを描画すれば、ゲーム独自のアイコンを表示することも可能です。デフォルトの設定では、システムのマウスカーソルが表示されないので注意してください。システムのマウスカーソルを表示するには Game クラスの IsMouseVisible プロパティを true に設定します。

マウスのボタンが押されているかどうかは、マウスボタンに対応するプロパティの値を調べます。左ボタンの状態は LeftButton プロパティ、右ボタンは RightButton プロパティ、中央ボタンは MiddleButton プロパティから得られます。加えて、一般に「戻る」や「進む」に割り当てらる 2 つの拡張ボタンは XButton1 プロパティXButton2 プロパティから得られます。

MouseState 構造体 LeftButton プロパティ
public ButtonState LeftButton { get; }
MouseState 構造体 RightButton プロパティ
public ButtonState RightButton { get; }
MouseState 構造体 MiddleButton プロパティ
public ButtonState MiddleButton { get; }
MouseState 構造体 XButton1 プロパティ
public ButtonState XButton1 { get; }
MouseState 構造体 XButton2 プロパティ
public ButtonState XButton2 { get; }

これらのプロパティが返す値は、ボタンが押されているかどうかを表す ButtonState 列挙型の値です。この値が Pressed であれば、マウスボタンが押されていると判断できます。

コード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, image1, image2;
    private Rectangle destinationRectangle;

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

    protected override void LoadContent()
    {
        sprite = new SpriteBatch(GraphicsDevice);
        image1 = Content.Load<Texture2D>("TestImage1");
        image2 = Content.Load<Texture2D>("TestImage2");

        base.LoadContent();
    }

    protected override void Update(GameTime gameTime)
    {
        MouseState state = Mouse.GetState();

        if (state.LeftButton == ButtonState.Pressed && texture.Bounds.Contains(state.X, state.Y))
            texture = image2;
        else texture = image1;

        Window.Title = "X=" + state.X + "Y=" + state.Y;

        base.Update(gameTime);
    }

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

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

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

コード1は、スプライト上でマウスの左ボタンが押されているとテクスチャが切り替わります。LoadContent() メソッドで 2 つの画像を読み込み、これを Texture2D 型の image1 と image2 フィールドにそれぞれ保存します。スプライトとして描画されるテクスチャは texture フィールドです。Update() メソッドの処理で、マウスの入力状態に従って image1 または image2 が代入されます。

マウスの座標がスプライトの上にあるかどうかは、スプライトを描画する領域を表す Rectangle 型の destinationRectangle フィールドと比較します。Rectangle 構造体は、指定した座標が長方形内にあるかどうかを Contains() メソッドで返してくれます。この結果が true であれば、カーソルがスプライトに重なっていると判断できます。

マウスホイール

主に画面のスクロールに用いられるマウスホイールの状態を取得するには、MouseState 構造体の ScrollWheelValue プロパティを使います。マウスホイールを前後に回転させると、回転した方向に従って、このプロパティに値が加算されます。

MouseState 構造体 ScrollWheelValue プロパティ
public int ScrollWheelValue { get; }

このプロパティが返す整数は、ホイールの回転方向に対する累積値です。ホイールが回転しているかどうかではないので注意してください。ゲーム開始時、ホイールの状態は 0 から始まります。ホイールを上にスクロール(ユーザーとは逆の方向)すると正数が加えられ、下にスクロール(ユーザーの方向)すると負数が加えられます。

ホイールを回転させた時にノッチ(「カチッ」とした手ごたえ)のある一般的なホイールであれば、一度の回転に 120 または -120 の値が加えられます。一方で、ノッチがないマウスホイールであれば、さらに細かい値が得られます。また、一部でホイールの加速度を設定する機能を備えたマウスも存在し、速く回転させれば大きい値が加えられ、ゆっくり回転させれば小さい値が加えられます。そのため、常に一定の値が返されることを期待してはいけません。正数または負数であるかによって方向を認識し、1 ノッチの値を基準に量を定めればよいでしょう。

多くの処理では、ScrollWheelValue プロパティの値をそのまま利用することはできません。一般的に必要な情報は、ホイールがどちらの方向に回転したかであって、ゲーム開始時からホイールが回転された累積値ではないでしょう。ホイールが回転した方向を調べるには、直前のホイールの値を保存しておき、新しいホイールの状態と比較します。その差が 0 ならば回転していない、そうでなければ 0 よりも大きいか小さいかで、回転した方向を判断できます。

コード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 Texture2D texture;
    private Vector2 position;
    private int prevValue;

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

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

        base.LoadContent();
    }

    protected override void Update(GameTime gameTime)
    {
        MouseState state = Mouse.GetState();

        if (prevValue < state.ScrollWheelValue)
            position.Y += -2;
        else if (prevValue > state.ScrollWheelValue)
            position.Y += 2;

        prevValue = state.ScrollWheelValue;

        Window.Title = "value=" + state.ScrollWheelValue;

        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);
    }
}
実行結果

コード2は、マウスホイールを回転させることでスプライトの位置を上下させることができるプログラムです。

Update() メソッドでは、マウスホイールの累積値を ScrollWheelValue プロパティから取得し、直前の累積値である prevValue と比較します。直前の累積値 prevValue が、現在の累積値 ScrollWheelValue よりも小さければ、ホイールが上にスクロールされていると判断できます。逆に prevValue が ScrollWheelValue よりも大きければ、下にスクロースされていると判断します。双方が同じ値の場合、ホイールは回転していません。

また、ウィンドウのタイトルバーに ScrollWheelValue の値を表示しています。この結果を見れば、ScrollWheelValue がゲーム開始以降のホイールを回転させた値の累積であることが確認できます。