d.sunnyone.org
sunnyone.org

ページ

2012-09-09

Taoを使ってC#/WPFでゲームパッドのボタンを読み取る

ちょっとしたツールを作るために、ゲームパッドをC#で書いたWPFアプリケーションから読もうと思ったが、意外とすっきりいかなかった。結論としては、Tao Frameworkというフレームワークに含まれるWin32 APIのwrapperを使うことで、気軽に読める。

---

ゲームパッド (Joystick? Joypad?)を読むにはDirectInputが定番らしくて、たしかに簡単そうに見えたのでチャレンジしてみたのだけど、managed DirectXを.NET 4で使うにはapp.configを書き替えないといけないとか、SetCooperativeLevelの第一引数がWindows.Windows.Forms.Controlだったりする罠(HWNDも取れるので実は後述の方法でいけるのだけど)にあったりして、挫折した。

ゲームパッドを読むためのAPIがWin32のwinmmというのにあるらしいとわかったが、P/Invokeの定義を書くのが面倒なので探してみたら、Tao Frameworkというゲーム用のフレームワークに定義されているらしい。調べてみると、MITライセンスなので使うことにした。

簡単な使い方

Joystick系のAPIはTao.Platform.Windowsに入っている。Tao Frameworkにはインストーラもあるのだけど、このdllを参照追加すればいいだけなので、zipを落としてdllだけ横に置くのが簡単でいいと思う。

参照追加したら、JOYINFO構造体をnewして、joyGetPos()というメソッドにjoypad IDをセットで渡せばおわり。IDはただの0からの連番。なお、joyGetNumDevs()は、つながっているデバイスの数を返すわけじゃないから注意だ。

for (int i = 0; i < Tao.Platform.Windows.Winmm.joyGetNumDevs(); i++)
{
    Tao.Platform.Windows.Winmm.JOYINFO joyinfo = new Tao.Platform.Windows.Winmm.JOYINFO();
    if (Tao.Platform.Windows.Winmm.joyGetPos(i, ref joyinfo) == Tao.Platform.Windows.Winmm.JOYERR_NOERROR)
    {
        this.textBlock1.Text += String.Format("Joypad[{0}] detected. Button: {1}\n", i, joyinfo.wButtons);
    }
}
パッドによってはもっと詳しい情報が取れるjoyGetPosEx()もあるらしい。自分の用途にはその必要がなかったので使わなかったけど、このへんのAPIの使い方についてはこのへんに書いてある。

イベント的に読み取る1: タイマーで読み取る

もうちょっと実用的に使うために、押されたことを検知したい。

API的には、joySetCapture()というメソッドがあり、これを使うと、ウィンドウメッセージを飛ばすことができる。しかし、引数からしてポーリングっぽい感じなので、WPFアプリケーションであれば、HWNDとか意識しなくていいので、タイマーで見たほうが素直だと思うのでそうした。実装はこのような感じ。


イベント的読み取る2: joySetCaptureで読み取る

それでもjoySetCaptureが使いたいならば、こんなかんじ。 一応動いた。

0 件のコメント:

コメントを投稿