こんにちは。
今回は、プログラムでプレイヤーが操作するマウスの状態を検知する方法を解説していきます。

1,マウスの状態

 マウスは、キーボードとは異なり様々な種類の状態を持っています。

 1つ目にマウスのボタンです。一般のマウスには左・右・中央の3つのボタンがあります。左のボタンは何かを選択したり決定したりするときに使用しますね。右のボタンはキャンセルしたりメニューを開くときにしばしば使います。中央のボタンはあまり使う機会が無いですね。

 2つ目にはマウス自体の移動があり、画面上のカーソル位置とも言い換えられます。マウスを移動させることで画面上の矢印を移動させて目的の位置に持ってきたり、ゲームでは視点をずらすために動かすこともありますね。

 今回は、この2つの種類の状態を、プログラム側で把握できるようにしましょう。


2,ボタン状態と”マウス移動”の取得

 マウスボタンが押されているかどうか、またはマウスが動かされたかの確認は、DirectInputを通じて行うことができます。以下のソースを御覧ください。
 
using SharpDX.DirectInput;


DirectInput directInput = new DirectInput();

//接続されているマウスを探す
Guid mouseGuid = Guid.Empty;
foreach (var g in directInput.GetDevices(DeviceType.Mouse, DeviceEnumerationFlags.AllDevices))
{
mouseGuid = g.InstanceGuid;
}
if (mouseGuid == Guid.Empty)
{
throw new Exception("マウスが見つかりません");
}

//デバイスを初期化
Mouse device = new Mouse(directInput);

//マウス状態の取得開始
device.Acquire();

//マウスの状態を取得する
MouseState state = device.GetCurrentState()

 この一連のコードでマウスの状態を取得することができます。
 気づいた方がいるかもわかりませんが、このコードは前々回の記事のキーボード状態の取得のコードと非常によく似ています。具体的には、キーボードの文字がマウスに変わっただけです。マウスもキーボードもやるべきことは大体同じなのです。

 コードの一番最後の行では念願の”マウスの状態”らしきMouseStateクラスを取得できています。このMouseStateクラスには、マウスのボタン状態とマウスの移動量が含まれています。再び下のコードを御覧ください。
//左ボタンがおされているか
bool buttonL = state.Buttons[0];

//右ボタンが押されているか
bool buttonR = state.Buttons[1];

//中央のボタンが押されているか
bool buttonCenter = state.Buttons[2];

//マウスの移動量(x:横 y:縦)
int mouseMoveX = state.X;
int mouseMoveY = state.Y;
 MouseStateクラスのButtonsプロパティは、bool配列になっており左ボタンの場合は1番めに、右ボタンは2番めに押されているかどうかの真偽値が格納されています。
 また、MouseStateクラスのX,Yプロパティにはそれぞれマウス自体の移動量が格納されているわけです。
 一度Mouseクラスを作ってしまえばいつでもGetCurrentState()メソッドによってマウスの情報を得ることができます。



3,”カーソル移動”の取得


 さて、ここまででマウスボタンと移動量を取得することが出来ました。これにより、画面上のボタンをクリックするインターフェースや、マウスの移動によって視点の向きを変える操作が可能になりました。しかし、そのようなインターフェースを扱う上で重要な画面上のカーソル位置がまだ判明していません。
 DirectInputとは、そもそもマウスやキーボードといった装置自体の状態を把握するための機能です。そのため、OS上で管理しているようなカーソルの位置は専門外であるため取得することができません。ですから今回は、DirectInputではなくOSに直接カーソルの位置を尋ねなければいけません。
 下のコードを御覧ください。

using System.Runtime.InteropServices;
//クラス内に記述
[DllImport("user32.dll")]
private static extern void GetCursorPos(ref POINT lpPoint);

private struct POINT
{
public UInt32 x;
public UInt32 y;
}

public void GetCursor(out int x, out int y)
{
POINT p = new POINT();
GetCursorPos(ref p);

x = p.x;
y = p.y;
}
 カーソル位置取得の場合は特に準備は必要なくて、単にAPIと関連付けた関数(上の例ではapiGetCursorPos)を呼び出せば大丈夫です。その点では、他の取得処理よりも楽ですね。



4,まとめ


 今回の内容をまとめると大きく2つです。
  • マウスのボタンや移動量をチェックするには、予め作成しておいたMouseクラスのGetCurrentState()メソッドを呼び出す。その返り値の、Buttonsメンバには[0]:左ボタン,[1]:右ボタン,[2]:中央ボタンの順で状態が格納されている。マウスの移動量は、XとYのメンバから取得する。

  • 画面上のカーソルの位置を取得するには、user32.dllのGetCursorPos()関数を呼ぶ。

 次回は、マウス状態をゲームライブラリに組み込む方法について模索したいと思います。おそらくキーボードの時と似たようなものになるでしょうが。