ちょっと、ジョイスティックを使ってみたくなりました。
というか、暇つぶしに、ジョイスティックを使ってプログラムを作ってみたくなりました。
何に使うかというと、部活で使ってるロボットとかマイコンをジョイスティックで (ry
色々使えそうなのでね。
PC から、シリアル (RS232C) で指令が送れればいいので、PC 側のプログラムだけ作ります。
今回は、どうすればジョイスティックの値を取得できるかテストしてみます。
使用する開発環境は、Visual C# 2005 です。(Express も OK)
自分のメモ代わりというか、C# でジョイスティック使うとなると、英語の資料しか見つからなかったし。
1. .NET Framework でジョイスティックを使うには。
DirectInput を使います。
DirectX の API の一部です。
面倒そうですが、意外と簡単でした。
ただ、Visual Studio 標準では、DirectX は使えない模様。
はじめに、DirectX SDK をインストールします。
2. DirectX SDK のインストール
Microsoft からダウンロードしてきます。
執筆時最新版は、March 2008 らしい。
あとは、普通にインストールします。
途中、こんなの出てくるけど、Unzip 押せば、解凍されてインストーラが開く。
WinZip とか、何気に懐かしい。
インストール完了。
ちなみに、プログラムリストの中には、いろんなものが入っている。
結構興味深いものもある。
3. DirectInput を使えるようにする
さっそく、いろいろ作ってみようかと思います。
Visual Studio 2005 を開いて、適当なプロジェクトを作成。
まず、DirectInput を使えるように、参照設定を追加します。
参照設定に追加するものは
- Microsoft.DirectX
- Microsoft.DirectX.DirectInput
この2つ、どちらも追加してあげてください。
DirectInput だけでは、なんかエラーでます。
4. さっそく試してみる。
MSDN とかで、DirectInput とかに関する情報を調べてみたんだけど・・・。
C++ とかはあるけど、C# が見つからない。
英語の資料は見つかったので、それを参考に。
まあ、大体コピペでいける。
まず、DirectInput を利用するので Form1.cs にこれを追加
using Microsoft.DirectX;
using Microsoft.DirectX.DirectInput;
で、あとこんな感じっていうのを下に乗せておく。
ややこしかもしれないけど。
Form1 Load でジョイスティックの初期設定。
Timer1 で、一定周期ごとに、Joystick の値を読み取ってる。
Interval は、とりあえず 10ms ぐらいにしてみた。
Button は 4 までだけど、実際はもっと増やせる。(面倒だった)
namespace DirectInput
{
public partial class Form1 : Form
{
Device joystick;public Form1()
{
InitializeComponent();
}private void Form1_Load(object sender, EventArgs e)
{
//create joystick device.
foreach (
DeviceInstance di in
Manager.GetDevices(
DeviceClass.GameControl,
EnumDevicesFlags.AttachedOnly))
{
joystick = new Device(di.InstanceGuid);
break;
}if (joystick == null)
{
//Throw exception if joystick not found.
throw new Exception("No joystick found.");
}//Set joystick axis ranges.
foreach (DeviceObjectInstance doi in joystick.Objects)
{
if ((doi.ObjectId & (int)DeviceObjectTypeFlags.Axis) != 0)
{
joystick.Properties.SetRange(
ParameterHow.ById,
doi.ObjectId,
new InputRange(-5000, 5000));
}
}//Set joystick axis mode absolute.
joystick.Properties.AxisModeAbsolute = true;//set cooperative level.
joystick.SetCooperativeLevel(
this,
CooperativeLevelFlags.NonExclusive |
CooperativeLevelFlags.Background);//Acquire devices for capturing.
joystick.Acquire();
}private void timer1_Tick(object sender, EventArgs e)
{
//Get
JoystickState state = joystick.CurrentJoystickState;
byte[] buttons = state.GetButtons();
int[] pov = state.GetPointOfView();//Output
trackBar1.Value = state.X;
trackBar2.Value = state.Y;
trackBar3.Value = state.Z;
trackBar4.Value = state.Rz;
checkBox1.Checked = (buttons[0] > 0);
checkBox2.Checked = (buttons[1] > 0);
checkBox3.Checked = (buttons[2] > 0);
checkBox4.Checked = (buttons[3] > 0);
textBox1.Text = pov[0]/100+"°";
}
}
}
joystick.Properties.SetRange の InputRange で、入力する値の範囲を設定できる。(繊細さ?)
MSDN に乗ってたのをそのまま使ったから 5000 になったけど、自分で扱いやすい値に設定したほうがいいと思う。
アナログスティックの値の取得は、joystick.CurrentJoystickState;
ボタンの状態の取得は state.GetButtons();
POV(ハットスイッチ) の取得は state.GetPointOfView();
な感じになっている。
アナログスティックは、軸が X, Y, Z, Rz ... となっている。
普通のコントローラーは、4軸までなので、ここまででいいと思うが、もっと増やすこともできる。
ボタンは、配列で入ってくるらしい。
ボタンの番号に対応している。
ON になると、byte 型 128 の値が返ってくる。 (OFF は 0)
POV に関しては、角度で帰ってくる。
たとえば右矢印を押した場合、9000 と帰ってくる。
斜め、上と右を押した場合は、4500 になる。
なにも押していないと -1 なので、0 は上ボタン。
なんて説明してきたけど、PS2 とかのコントローラーを例に取ってるので、あしからず。
5. 最後に
今回は、機嫌がいいので、プロジェクトを置いておく。
ほしい人は、ダウンロードしていってもいいよ。と。
というわけで、終了。
ぐりぐり回すの気持ち良いね。
これを見て、わからないこととかあるなら質問も OK です。
コメントからいただければ、わかる範囲でこたえます。

コメントする