XNA でゲーム作っててぐえぇぇ…ってなるのが、ゲームコントローラーの扱いです。
デフォルトではXBOX のコントローラーしか認識してくれず、とても辛い気分になる。Unity とかデフォルトで用意してくれてるし、その部分はユーザーが用意すべき部分ではないように思う。
XNA は開発が停止され、今はMonogame だけど、そこでnot XBOXコントローラーを使う方法をなんとかしたのでメモメモ。
今回はManaged DirectX を利用することにしました。
ちなみに環境は
- Visual Studio 2013, 2015RC
- Monogame 3.4
です。
準備
適当なプロジェクトを作って下さい。
参照
Microsoft.DirectX, Microsoft.DirectX.DirectInput をそれぞれ参照したい……のですが、多分この2つはソリューションエクスプローラーから普通に参照に追加しようとしても出てこないので、直に探しに行きます。
僕の環境だと
以下にそれぞれありましたので、両方追加します。
あとusing のとこに
using Microsoft.DirectX.DirectInput;
を追加します。
App.config
このままとりあえずビルドしてみようとすると、
「混合モード アセンブリはバージョン ‘v1.1.4322′ のランタイムに対して作成されており、追加の構成情報がないと 4.0 ランタイムでは読み込めません。」
と怒られると思います。
新しい項目の追加 で、アプリケーション構成ファイル を追加し、
<configuration> <startup useLegacyV2RuntimeActivationPolicy="true"> <supportedRuntime version="v4.0"/> </startup> </configuration>
を書くと大丈夫です。
ちなみにビルドすると (アプリケーション名).exe.config が bin/x86/Debug/ 以下に作られますが、これが無いとexe は動かないので注意。
コード
以下、コードです。
// 適当に宣言 Device joystick = null; DeviceList devList; // initialize っぽいところで devList = Manager.GetDevices(DeviceClass.GameControl, EnumDevicesFlags.AttachedOnly); foreach (DeviceInstance dev in devList) { joystick = new Device(dev.InstanceGuid); break; } joystick.SetDataFormat(DeviceDataFormat.Joystick); joystick.Acquire(); // update っぽいところで if (joystick == null) { return; } else { JoystickState state = joystick.CurrentJoystickState; foreach (var btn in state.GetButtons()) { int id = Array.IndexOf(state.GetButtons(), btn); if (state.GetButtons()[id] == 128) { Console.WriteLine(id + " is pushed!!!!!!!!!"); } } // 十字キーの状態 Console.WriteLine("X: " + state.X); Console.WriteLine("Y: " + state.Y); }
十字キーは0, 32768, 65535が返ってきます。アナログだったら0~65535が返ってくるんですかね。
とりあえずこれでめでたいはず!