C++ Joystick Reader and Calibrator for Mac OS X

1. はじめに

このページでは、Mac OS X用のジョイスティック読み取り関数とそのサンプルコード、それと、ジョイスティック調整プログラムをダウンロードできる。Win 32 APIだと、joyGetPosEx関数一発でジョイスティックの状態を読み取ることができるが、Mac OS Xだと、それに比べて結構長いプログラムを書かないと、ジョイスティックの状態を読み取ることができない。さらに悪いことに、Windowsだとコントロールパネルのゲームコントローラ の設定を使ってジョイスティックの調整ができるが、Mac OS Xには、そのような調整プログラムは無い。もしも、ジョイスティックの製造元が親切なら、ジョイスティックに調整プログラムが付属してくるかもしれない けど、そうでなければ、各プログラムごとにジョイスティックを調整しなくてはならない。多分、関数一発でジョイスティックの読み取りができない点と、自力で調整プログラムまで書かなくてはならないというのが、Windows用に書かれたゲームをMac OS Xに移植しようとしても、やる気をくじく要因になっているのではないだろうか。

自分でもYSFLIGHTを移植しようとしていて、同じ問題に直面して、仕方ないんで、ジョイスティック読み取り関数と、調整プログラムを書いた。なので、ひょっとして同じ問題を持っている人がいるようなら、役に立つかもしれない。

なお、このページからダウンロードできるソースコード、プログラムは、それを利用した結果について、使用者が全責任を負うものとして、作者は責任を負わないという点に同意していただけるのであれば、フリー、商用、オープンソース、プロプライエタリなプロジェクトを問わず、自由に組み込んでいただいても構わない。この点に同意できないのであれば、このページからダウンロードできるソースコード、プログラムの利用は禁止する 。また、このページからダウンロードできるソースコードは、組み込んだからといって、ソースコードの公開の義務は発生しない

寄付歓迎

もしも、ysflight.comのコンテンツ作成に、1000円ぐらい寄付してもかまわない、という方がいましたら、以下URLより一口1000円でご送金いただけると大変感謝いたします。Polygon Crestの購入ということになってますが、ここから寄付いただけると非常にありがたいです。

← Vectorシェアレジで1000円寄付。なお、手数料と消費税は別にかかります。

ご送金いただいた金額は、開発環境のアップグレード、資料の購入、その他YSFLIGHT.COMのメンテナンス、コンテンツ作成の費用に使わせていただきます。よろしくお願いします 

2. ダウンロード

Joystick Reader, Calibrator, ソースファイル (for Mac OSX)

Joystick Reader & Calibrator, ソースファイル (for Linux 一応)

3. ジョイスティック読み取り関数/クラスの説明

このジョイスティックリーダーは、次の3本のファイルで構成されている。

  • ysjoyreader.h
  • ysjoyreader.cpp
  • ysjoyreader-objc.m

プログラムの最初に、

YsJoyReaderSetUpJoystick

を呼ぶことで、ジョイスティックを初期化できる。この関数は、呼び出し側でYsJoyReaderクラスの配列を確保して、その配列へのポインタと配列の長さをパラメータとして渡すと、検出できたジョイスティックの個数を返す。

続いて、

YsJoyReaderLoadJoystickCalibrationInfo

この関数に、検出されたジョイスティック個数とYsJoyReaderクラスの配列をパラメータとして与えることで、調整情報をファイルから読み込む。ファイル名は、~/.ysjoycalib で、ジョイスティック調整プログラムが生成する。ファイルが存在しない場合は、この関数は何もしない。中身はテキストファイルなので、読めば大体何が書いてあるかわかると思う。

YsJoyReaderクラスには、次のメンバー変数がある。

YsJoyReaderAxis axis[YsJoyReaderMaxNumAxis];
YsJoyReaderButton button[YsJoyReaderMaxNumButton];
YsJoyReaderHatSwitch hatSwitch[YsJoyReaderMaxNumHatSwitch];

それぞれのクラス (YsJoyReaderAxis, YsJoyReaderButton, YsJoyReaderHatSwitch)はysjoyreader.hの中で定義されている。それぞれの要素には、existというメンバー変数があり、この値で要素が存在するか確認できる。例えば、次のような記述で、ジョイスティックに第3軸があるかを確認できる。

if(reader.axis[2]!=0)
{
    // 第3軸がある場合の処理
}

YsJoyReaderクラスのRead関数を使うことで、ジョイスティックから各要素の値を読み取ることができる。調整後の軸の値(-1.0から1.0)を得るには、

double axis0;
axis0=reader.axis[0].GetCalibratedValue();

また、ボタン0の状態は、次のように読み取ることができる。

if(reader.button[0].value!=0)
{
    // Button is pressed!
}

ハットスイッチの状態は、次のような記述で確認できる。

switch(reader.hatSwitch[0])
{
case 0: // hat switch neutral
    break;
case 1: // up
    break;
case 2: // up-right
    break;
case 3: // right
    break;
case 4: // down-right
    break;
case 5: // down
    break;
case 6: // down-left
    break;
case 7: // left
    break;
case 8: // left-up
    break;
}

一応、ハットスイッチは4個まで対応している。(まだハットスイッチを複数搭載したジョイスティックって見たことないけど)

プログラムを終了する前に、YsJoyReaderのReleaseInterface関数でインターフェースを解放してもいいが、今時のOSだと、プログラムごとに確保していたリソースぐらいは覚えていて、終了と同時に解放してくれると思うので、多分しなくてもいいと思う。

このジョイスティックリーダーを組み込んでコンパイルするには、次のフレームワークが必要になる。 なので、Xcodeからコンパイルするときは、フレームワークに、次のふたつのフレームワークを追加しておかないと、リンクエラーが出る。

  • IOKit
  • Foundation

サンプルコード、sample.cppは、次のコマンドでコンパイルできる。

g++ sample.cpp ysjoyreader.cpp ysjoyreader-objc.m -framework IOKit -framework Foundation

このサンプルコードは、シンプルなターミナル用プログラムで、実行すると、一秒ごとにジョイスティックの各軸、ボタン、ハットスイッチの状態をコンソールに出力する。

(sample.cpp)

#include <stdio.h>
#include <ysjoyreader.h>
#include <unistd.h>

const int maxNumJoystick=4;
int numJoystick;
YsJoyReader joystick[maxNumJoystick];

int main(void)
{
    YsJoyReaderSetUpJoystick(numJoystick,joystick,maxNumJoystick);
    YsJoyReaderLoadJoystickCalibrationInfo(numJoystick,joystick);

    while(1)
    {
        int i,j;
        for(i=0; i<numJoystick; i++)
        {
            joystick[i].Read();

            printf("Joy[%d]",i);
            for(j=0; j<YsJoyReaderMaxNumAxis; j++)
            {
                if(joystick[i].axis[j].exist!=0)
                {
                    printf(" Ax%d:%+5.2lf",j,joystick[i].axis[j].GetCalibratedValue());
                }
            }
            for(j=0; j<YsJoyReaderMaxNumButton; j++)
            {
                if(joystick[i].button[j].exist!=0)
                {
                    printf(" Bt%d:%d",j,joystick[i].button[j].value);
                }
            }
            for(j=0; j<YsJoyReaderMaxNumHatSwitch; j++)
            {
                if(joystick[i].hatSwitch[j].exist!=0)
                {
                    printf(" POV%d:%d",j,joystick[i].hatSwitch[j].GetDiscreteValue());
                }
            }
            printf("\n");
        }

        sleep(1);
    }

    return 0;
}

4. ジョイスティック調整プログラム

ジョイスティック調整プログラム(YsJoystickCalibrator)は、ジョイスティックの軸の中立位置、最大位置、最小位置の偏りを検出して、その状態をホームディレクトリの.ysjoycalibというファイルに記録することができる。上のジョイスティックリーダーは、この.ysjoycalibを読み込んで、中立位置で値がゼロになるように、ジョイスティックの軸の値を調整することができる。

ジョイスティックは、この調整プログラムを起動する前に接続しておく必要がある。プログラムがジョイスティックを正しく認識できれば、軸とボタンの状態がウィンドウに表示される。

ジョイスティックの調整を始める前に、まず、ジョイスティックの種類を選ぶ必要がある。例えば、操縦桿とボタンだけならば「Only One Stick/Yoke」、操縦桿とスロットルレバーなら「1:Stick 2:Throttle」を選ぶと正しく調整できる。正しいジョイスティックの種類を選ばなくても調整はできるが、軸には二種類あって、中立位置が重要なもの(操縦桿、ラダーペダルなど)と、最大位置と最小位置だけが重要なもの(スロットルレバーなど)がある。ジョイスティックの種類を正しく選ばないと、スロットルレバーで中央位置決めをしなくてはならなかったり、調整の途中で、一部不自然な操作をしなくてはならなくなる。

続いて、「調整(Calibrate)」メニューから「調整(Calibrate)」を選んで、画面の指示に従ってジョイスティックを動かすことで、ジョイスティックを調整できる。調整が完了すると、自動的にホームディレクトリの.ysjoycalibというファイルに調整情報が保存される。

新しいジョイスティックを接続した場合など、調整情報が合わなくなってしまった場合や、新しいジョイスティックに専用の調整プログラムが付属していて、この調整プログラムで再調整の必要が無い場合は、「調整(Calibrate)」メニューの「調整情報の全消去 (Erase All Calibration Data)」を選ぶことで、調整情報を消去することができる。あるいは、手動でホームディレクトリの.ysjoycalibを削除することでも、調整情報を消去することができる。


調整プログラムのスクリーンショット(クリックで拡大)

[更新履歴]

2015/04/03

  • XCode 6でコンパイル。どうも、XCode 3.xでコンパイルしたバイナリだとOSX Yosemiteで動かないらしい。
  • Microsoft Keyboardをジョイスティックと誤認する問題を修正。IOHIDDeviceConformsToという関数でジョイスティックとして使えるかどうかがチェックできることをたまたま見つけたんで助かった。
  • ビルドをmakefile手書きからCMakeに変更。

2010/01/27

Mac OS 10.6に対応。Hat Switchから出てくる生の値がジョイスティックによって違うらしいので、GetDiscreteValueという関数でどのジョイスティックでも共通に 0:中立  1:前  2:右前  3:右  4:右後  5:後  6:左後  7:左  8:左前 の値になるようにしたつもり。Apple Developer Connectionには、結構探したけど、ジョイスティックAPIが返してくる値に関する説明が無いので、どのジョイスティックでも共通に使えるかどうかは不明。

2009/10/17

公開。