MonoGameでマウスを使う方法


MonoGameでマウスを使う方法を解説します。



マウスカーソルを表示させる

初期状態では、MonoGameで作ったゲームはマウスカーソルが表示されません。
表示させるにはGameクラスのIsMouseVisibleプロパティにtrueを設定します。
Gameクラスのコンストラクタで行えば良いでしょう。
public Game1()
{
    graphics = new GraphicsDeviceManager(this);
    Content.RootDirectory = "Content";

    // マウスカーソルを表示する
    IsMouseVisible = true;
}

カーソルの位置を取得する

MouseクラスのGetState()メソッドを使うとMouseStateのインスタンスが取得できます。これにはカーソル位置や、現在マウスのボタンが押されているかどうかなどの情報が格納されています。
MouseStateのXまたはYを参照すると、カーソルの位置がわかります。
protected override void Update(GameTime gameTime)
{
    if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
        Exit();

    // Mouseの状態を取得
    MouseState mouseState = Mouse.GetState();

    // カーソル位置をConsoleに表示してみる。
    System.Console.WriteLine("MouseX:" + mouseState.X + ", MouseY:" + mouseState.Y);

    base.Update(gameTime);
}
F5キーで実行し、VisualStudioの出力ウィンドウを確認してください。
※Ctrl+F5ではログが出ないので、F5で実行してください

マウスのボタンが押されているか調べる

マウスのボタンが押されているかどうか調べるには、以下のようにします。

protected override void Update(GameTime gameTime)
{
    if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
        Exit();

    // TODO: Add your update logic here

    // マウスの左ボタンが押されているか調べる
    if (Mouse.GetState().LeftButton == ButtonState.Pressed)
    {
        System.Console.WriteLine("左ボタンが押されています。");
    }
    else
    {
        System.Console.WriteLine("左ボタンが押されていません。");
    }

    base.Update(gameTime);
}
MouseStateのLeftButtonプロパティは、マウスの左ボタンが押されているかどうかを表す値(enum)を返却します。
押されていることを表すButtonState.Pressedまたは押されていないことを表すButtonState.Releasedと比較してください。

右ボタンを調べたい場合は、LeftButtonではなくRightButtonプロパティを参照してください。

押された瞬間、離された瞬間を検出する

ボタンが押された瞬間や離された瞬間を検出するのは地味に面倒です。現在の状態と1フレーム前の状態とを比較する必要があるからです。そのためには、1フレーム前の状態を保存しておかなければなりません。

// 1フレーム前のマウスの状態
MouseState prevMouseState;

protected override void Update(GameTime gameTime)
{
    if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
        Exit();

    // TODO: Add your update logic here

    // 現在のマウスの状態
    MouseState currentMouseState = Mouse.GetState();

    if (currentMouseState.LeftButton == ButtonState.Pressed &&
        prevMouseState.LeftButton == ButtonState.Released)
    {
        System.Console.WriteLine("今押された!");
    }

    if (currentMouseState.LeftButton == ButtonState.Released &&
        prevMouseState.LeftButton == ButtonState.Pressed)
    {
        System.Console.WriteLine("今離された!");
    }

    prevMouseState = currentMouseState;

    base.Update(gameTime);
}

一般的に「クリック」というのは、ボタンを「離した瞬間」に発動します。では、ゲームもその通りにしたほうが良いかというと、ゲームのジャンルによります。
パズルゲームなどでは、一般的なクリックと同様に、離した瞬間に処理を行うようにすると良いでしょう。
マウスのボタンで銃を撃つようなアクション性の強いゲームでは 、押した瞬間に処理を行ったほうが気持ち良いゲームになるでしょう。

ホイールのスクロールを検出する

Mouse.GetState().ScrollWheelValueを参照すると、ゲーム開始時からどれくらいマウスホイールが回転したかが返却されます。
System.Console.WriteLine(Mouse.GetState().ScrollWheelValue);
大抵は、1フレーム前の値と比較して、どれくらい回転したかを算出することになるでしょう。

【応用】判定処理をまとめたクラスを作る

マウスが押されたことを調べるのに、いちいち上記のような条件式を書くのはちょっと面倒です。ミニゲーム程度なら不要ですが、ある程度のボリュームのゲームを作るなら、判定処理をまとめたクラスをあらかじめ作っておくと、トータルでは楽です。

using Microsoft.Xna.Framework; // Vector2を使うために必要
using Microsoft.Xna.Framework.Input; // Mouseを使うために必要

namespace 任意の名前空間
{
    static class Input
    {
        // 現在のマウスの状態
        static MouseState currentMouseState;
        // 1フレーム前のマウスの状態
        static MouseState prevMouseState;

        public static void Update()
        {
            prevMouseState = currentMouseState;
            currentMouseState = Mouse.GetState();
        }

        // マウス左ボタンが押された瞬間かどうかを返却する
        public static bool IsMouseButtonDown()
        {
            return currentMouseState.LeftButton == ButtonState.Pressed
                && prevMouseState.LeftButton == ButtonState.Released;
        }

        // マウス左ボタンが離された瞬間かどうかを返却する
        public static bool IsMouseButtonUp()
        {
            return currentMouseState.LeftButton == ButtonState.Released
                && prevMouseState.LeftButton == ButtonState.Pressed;
        }

        // マウスの左ボタンが押されているかどうかを返却する
        public static bool IsMouseButton()
        {
            return currentMouseState.LeftButton == ButtonState.Released;
        }

        // マウスカーソルの場所を返却する
        public static Vector2 MousePosition
        {
            get
            {
                return new Vector2(currentMouseState.X, currentMouseState.Y);
            }
        }

        // スクロールホイールの変化量を返却する
        public static int GetMouseWheel()
        {
            return prevMouseState.ScrollWheelValue - currentMouseState.ScrollWheelValue;
        }
    }
}


使い方は以下のようになります。ゲームのメインのUpdateメソッドの最初の方で、今回作ったInputクラスのUpdateを呼んでおく必要があります。

protected override void Update(GameTime gameTime)
{
    if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
        Exit();

    // TODO: Add your update logic here

    // 他のどのロジックよりも先に呼び出しておく
    Input.Update();

    if (Input.IsMouseButtonDown())
    {
        System.Console.WriteLine("マウス左ボタンが今押された!");
        System.Console.WriteLine("X:" + Input.MousePosition.X + ", Y:" + Input.MousePosition.Y);
    }

    base.Update(gameTime);
}

マウスのボタンが押されたかどうかを調べることは頻繁に行うため、最初にこのようなクラスを作っておくことが、その後の開発作業の効率を高めてくれます。
一度作っておけば、コピペで他のプロジェクトにも転用できますしね。

0 件のコメント:

コメントを投稿