霊安日記

jf_nights の霊安草子。

Monogame で XBOXコントローラーじゃないコントローラーを使いたいマン

XNA でゲーム作っててぐえぇぇ…ってなるのが、ゲームコントローラーの扱いです。
デフォルトではXBOX のコントローラーしか認識してくれず、とても辛い気分になる。Unity とかデフォルトで用意してくれてるし、その部分はユーザーが用意すべき部分ではないように思う。

XNA は開発が停止され、今はMonogame だけど、そこでnot XBOXコントローラーを使う方法をなんとかしたのでメモメモ。
今回はManaged DirectX を利用することにしました。

ちなみに環境は

です。

準備

適当なプロジェクトを作って下さい。

参照

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が返ってくるんですかね。


とりあえずこれでめでたいはず!