ゲームパッドを使うには

◆PROCESSING 逆引きリファレンス

 カテゴリー:ゲーム作成

ゲームパッドを使うには

【概要】

PROCESSINGはマウスやキーボードからの入力を手軽に扱うことができて便利なのですが、ゲームなどではゲームパッドからの入力を扱いたいことがあります。

残念ながらPROCESSINGの標準命令だけではゲームパッドは扱えません。しかしPROCESSINGには、このような用途に適した Game Control Plus ライブラリがあります。

今回はGame Control Plus ライブラリを使ってゲームパッドからの入力を受け取る方法について紹介したいと思います。

なおGame Control Plus ライブラリについては、以下のサイト様などが参考となります。私も大いに参考とさせていただきました。ありがとうございます。

 

準備

以下の手順に従って、PROCESSINGに Game Control Plus ライブラリを追加します。

標準エディタを起動し、メニューの「スケッチ」から「ライブラリをインポート」を選択します。

次に、サブメニューから「ライブラリを追加」を選択します。Contribution Manager 画面が開きます。

Contribution Manager 画面の左端にある Libraries タブを選択し、一番上の検索窓に「GAME」と入力します。

「Game Control Plus | Use joysticks, gamepads a…」とかかれた行を選択し、右下にある Install ボタンを 押下してください。

2018/10 月現在、Ver1.2.1 がインストールされました。

ゲームパッドを使うだけなら Game Control Plus ライブラリだけでも可能ですが、ゲームパッドの接続状態を確認するには、別途 G4P ライブラリが必要になります。

G4P ライブラリは、一番上の検索窓に「G4P」と入力する事で表示されます。Game Control Plus ライブラリと同じ手順で、インストールしておくと良いでしょう。

 

ゲームパッドについて

ゲームパッドはご存知の通り、PlayStationやXboxに添付されている操作用のパッドの事ですね。

非常に沢山の種類がありますが、パソコンで利用可能なものは主にUSBに接続するタイプです。

最近は Bluetooth 接続のゲームパッドもあるようですが、 手持ちにそんなゲームパッドがないため、Game Control Plus ライブラリで使えるかどうかは未確認です(汗)。

ゲームパッドの入力方式にはDirectInput方式とXInput方式の2種類があります。また入力を処理する方式としてデジタル入力とアナログ入力の2つがあります。

アナログ入力とデジタル入力の違いは、主にステックの感度になります。アナログの場合は滑らかな入力値が、デジタルの場合はON/OFFの入力値が得られます。

最近のゲームでは、車のアクセルやビームの強度、ジャンプする高さなどを表現するために、入力値が細かく得られるアナログ入力が好まれるようです。

Game Control Plus ライブラリは、DirectInput方式とXInput方式の両方に対応しています。またデジタル入力とアナログ入力の両方にも対応しています。

ただし手持ちのゲームパッドで試した限りにおいては、ゲームパッドをデジタル入力方式で接続した時は、スティックの認識に不具合があるようでした。

ゲームパッドの各部分には、Game Control Plus ライブラリにより独特の名称がつけられています(ゲームパッドメーカーによる正式呼称とは異なります)。以下はELECOMのJC-U4013SBKの例です。


(画像URL:ELECOM 様 JC-U4013SBK)

ボタンやスライダーとして認識可能な数はゲームパッドによって異なります。またDirectInput方式では、ボタンやスライダーの内部番号と実際の物理的な位置は、ゲームパッドによってバラツキがあり統一されていません。

したがって、もしもあなたがDirectInput方式で接続されている様々なメーカーのゲームパッドに対応するプログラムを作る必要があるのなら、かなり面倒臭い処理が必要となります。

DirectInput方式のゲームパッドに対応する多くのアプリケーションで、ゲームパッドのボタンをカスタマイズする画面や機能があるのは、このためです。

 

ゲームパッドの接続を確認する

ゲームパッド(デバイス)をGame Control Plus ライブラリで操作する前に、該当デバイスが正常に認識できることを確認しておくと良いでしょう。また、あらかじめデバイスの名前や、各ボタン、スライダーなどの部品の名前を調べておくと便利です。

デバイスの名前や各部品の名前を調べるには、Game Control Plus ライブラリが提供している Configuratorツールを利用します。

なおConfiguratorツールを利用するには G4P ライブラリが必要になりますので、事前にインストールしておいて下さい。

Configuratorツールを使うには、標準エディタのファイル->サンプルを選択してサンプルウィンドウを開き、ツリーのGame Control Plusの中にあるConfiguratorをダブルクリックします。

ダブルクリックすると、何やらコーディングされたプログラムが開くので実行します。

プログラムを実行すると以下のようなウィンドウが開きますので、表示されているデバイスの中から、ゲームパッドと思われるものを探してください。


私のPCでは、JC-U4013S Direct Input Mode という名前のゲームパッドが見つかりました。

ここで大切なのがゲームパッドの「名前」になります。この名前でゲームパッドをOPENして、利用することになるからです。

運悪く名前が文字化けしてしまっている人は、ゲームパッドの番号でアクセスする事も可能です。

しかしゲームパッドの番号は、以降で説明するスライダーやボタンの番号とは異なり、ゲームパッドをPCに接続するたびに変化する可能性があるため、推奨できません。

ゲームパッドの名前が文字化けしている人は、下記「デバイス一覧を得る」の記事内容を参考にしながら、デバイスをOPENして下さい。

続いて上記画面の左横にある丸いボタンを押下すると、以下のような画面が開きます。


PCに接続されているゲームパッドの種類によって画面のデザインが異なる事がありますが、選択したゲームパッドが持っているボタンやスライダーなどの部品を一覧形式で確認できます。


右上にあるのがスライダー情報です。本例では4つのスライダーがある事がわかります。数はゲームパッドにより異なります。

上から順番に0番、1番、2番、3番になります。

重要なのは番号と、名前と、MAX/中央値です。名前が文字化けしていない人は、この名前(上記例なら、XとかY)を使ってスライダーにアクセスできます。文字化けしてしまっている人はスライダーの番号でアクセスします。

MAX/中央値は、該当スライダーの傾斜具合によって得られる値です。中央値を境に +MAX ~ -MAX まで値が変化します。

ゲームパッドのスライダーを操作すると画面上の値が変化します。どの名前(あるいは番号)のスライダーがどれに対応するのかを、しっかりと覚えておきましょう。


スライダー情報の下に表示されているのが、ボタン情報です。本例では13個のボタンがある事がわかります。数はゲームパッドにより異なります。

普通は、上から順番に0番、1番、2番、3番 ・・・ となります。ただし、後述するハット情報との兼ね合いで、1番、2番・・・というように、番号が1から始まる事もあるため、注意して下さい。

重要なのは番号と、名前です。名前が文字化けしていない人は、名前を使ってボタンにアクセスできます。文字化けしてしまっている人はボタンの番号でアクセスします。

私の例では、全部のボタンが文字化けしてしまっていますね・・・(汗)。

ここでもゲームパッドのボタンを操作すると画面上の●印が光るので、どの名前(あるいは番号)のボタンがどれに対応するのかを、覚えておいて下さい。


最後に、ボタン情報の下に表示されているのがハット情報です。

重要なのは番号と、名前です。名前が文字化けしていない人は、名前を使ってハットにアクセスできます。文字化けしてしまっている人はハットの番号でアクセスします。

ハット情報がボタン情報の下に表示されている場合は、ボタンの最後の番号+1 番が、該当ハットの番号になります。例えばJC-U4013Sであれば、ボタンが0番から12番まであったので、ハットは13番になります。

ハット情報がボタン情報の上に表示されている場合は、ハットが0番になり、ボタンは1番から始まります。


上記のゲームパッドではハット情報がボタン情報の上に表示されていますので、ハットが0番、最初のボタンは1番になります。

 

【詳細】

ControlIOインスタンスを取得する

ゲームパッドを扱うには、まずは ControlIOクラスのインスタンスを取得し、ControlIOクラスを利用してゲームパッド(デバイス)を取得して、該当デバイスを OPEN する必要があります。
.

インスタンスを取得するControlIO control = ControlIO . getInstance (PApplet app) ;

app : PApplet。this を与える
control : ControlIO インスタンス

ControlIO の staticメソッドである getInstance() でインスタンスを取得します。インスタンスの取得は簡単ですね。

 

デバイスを取得する

デバイスを取得するControlDevice device = control . getDevice (int deviceNumber);
ControlDevice device = control . getDevice (String deviceName);

deviceNumber : ゲームパッドの番号
deviceName : ゲームパッドのデバイス名
control : ControlIO インスタンス
device : デバイスインスタンス

ControlIOのインスタンスを取得したら、デバイスを取得します。

デバイスを取得するには、あらかじめ対象となるデバイスの名前もしくは番号がわかっている必要があります。デバイスの名前は、前述の手順で事前に調べておくことになります。

上記例では、デバイスの名前を指定して取得しています。デバイスが見つからないとRuntimeException が発生するので注意してください。

 

デバイスをOPENする

OPENするvoid device . open ( );

device : デバイスインスタンス

デバイスが取得できたらOPENします。

 

デバイス一覧を得る

それではデバイス名が不明な場合や、デバイス名が文字化けしていて指定できない場合は、どうすれば良いでしょうか?

ControlIOクラスには、ライブラリが認識しているデバイスの一覧を取得するgetDevices()メソッドがあります。
.

OPENするList devList = control.getDevices();

control : ControlIO インスタンス
devList : デバイス一覧

このメソッドでデバイスの一覧を取得し、デバイスの種類がゲームパッドのものを取り出す事で対応する方法が考えられます。

ControllerのTypeには、以下の定数が利用可能です。

項番 定義 説明
1 UNKNOWN 不明
2 MOUSE マウス
3 KEYBOARD キーボード
4 FINGERSTICK フィンガースティック
5 GAMEPAD ゲームパッド
6 HEADTRACKER ヘッドトラッカー
7 RUDDER ラダー
8 STICK Joyスティック
9 TRACKBALL トラックボール
10 TRACKPAD トラックパッド
11 WHEEL ホィール

FINGERSTICKやHEADTRACKERといった見慣れないデバイスもありますが(笑)、ゲームパッドとして扱うなら STICK、FINGERSTICK、GAMEPAD あたりが対象となるでしょう。

デバイスをOPENする部分は、以下のような感じで1つの関数としてまとめた方が良いでしょう。

 

ボタン、スライダー、ハットを取得する

ボタンとスライダーを取得するControlButton button = device. getButton(int buttonNumber);
ControlButton button = device. getButton(String buttonName);
ControlHat hat = device . getHat(int hatNumber);
ControlHat hat = device . getHat (String hatName);
ControlSlider slider = device. getSlider(int sliderNumber);
ControlSlider slider = device. getSlider(String sliderName);

buttonNumber : ボタン番号
buttonName : ボタン名
hatNumber : ハット番号
hatName : ハット名
sliderNumber : スライダー番号
sliderName : スライダー名
button : ボタンインスタンス
hat : ハットインスタンス
slider : スライダーインスタンス
device : デバイスインスタンス

上記例の openDevice() は、上で説明したデバイスをOPENする処理をまとめた関数です。

名前または番号を指定して、ボタンオブジェクト、ハットオブジェクト、スライダーオブジェクトを取得します。それぞれの名前や番号は、前述の手順で事前に調べておくことになります。

 

ボタンとスライダー数を取得する

ボタンを取得するint buttonNum = device. getNumberOfButtons();
int sliderNum= device. getNumberOfSliders();

buttonNum : ボタン数
sliderNum : スライダー数
device : デバイスインスタンス

該当ゲームパッドに搭載されているボタン数とスライダー数を取得します。ハットの数を取得する命令は無いようです。

注意としては、ハットがボタンとして数えられる事です。私が持っている JC-U4013S では、そのようになりました。

正確にボタンの数だけ(あるいはハットの数だけ)知りたい場合は、ボタンインスタンスを0番から getNumberOfButtons() 数まで取得し、該当ボタンインスタンスのクラス名を見るしかなさそうです。

例えば上記では、CLass名でハットかボタンかを識別し、Hatの番号を得て、ハットインスタンスを取得しています。なんかダサイですけど・・・他に良い方法が見つかりませんでした。

 

ボタンイベント

ボタンイベントを定義するvoid button . plug( Object obj, String methodName, int eventType );

button : ボタンインスタンス
obj: イベントを受け取るクラス。通常は this
methodName : イベントを受け取るメソッド名
eventType : イベントの種類。ON_PRESS, ON_RELEASE, WHILE_PRESS

ボタンには、押した時(ON_PRESS)、離した時(ON_RELEASE)、押しっぱなしの時(WHILE_PRESS)に対応するイベントを定義できます。

それぞれ ControlIO クラスの定数で指定します。

メソッド名には、該当イベントを受け取る「 void型で、引数なし」のメソッド名を指定します。

こんな感じですね。

plug() で指定したメソッド名に一致するメソッドが見つからない場合や、引数の数が一致しない場合(引数ありのメソッドを指定した場合)は、実行時に例外が発生するので注意してください。

またリファレンス上ではハットにも同様のイベントを定義できることになっていますが、手持ちの JC-U4013S では例外エラーとなってしまいました。

ゲームパッドによっては、ハットにはイベントを定義できないようですので注意してください。

 

ボタン押下判定

ボタン押下判定Boolean pressed = button . pressed();

button : ボタンインスタンス
pressed : 押されている時 true

その瞬間にボタンが押されているかどうかは、ボタンクラスの pressed() メソッドで判定可能です。

presswd() メソッドを draw() 関数などから適当に検査すれば、その瞬間のボタンの挙動を判定できます。

 

スライダー値

スライダー値float val = slider . getValue();

slider : スライダーインスタンス
val : スライダーからの値

スライダーインスタンスの getValue() メソッドで、該当スライダーの現在値を取得できます。

スライダー値は、スライダーの傾斜に伴い変化します。スライダー値が変化する範囲は、getMultiplier() と getTolerance() で取得できます。

JC-U4013S では、getMultiplier() は +1.0 を、getTolerance() は 0.0 を返します。したがって値の変化する範囲は、+getMultiplier() から getTolerance()と、-getTolerance() から getTolerance() になります。

getMultiplier() が 1.0、getTolerance() が 0.0 の場合、左右スライダーなら 真左が -1.0、真右は +1.0 、上下スライダーなら真上が -1.0、真下は +1.0 になります。

(画像URL:ELECOM 様 JC-U4013SBK)

ただしスライダーが真ん中(静止状態)にあっても、正確に 0 を示さない事があるので注意してください(0に近い値にはなります)。

また一部のゲームパッドでは、デジタル入力時においてスライダーから変化値を拾えない事があるようです。

なにかの不具合っぽい感じがしますが、ゲームパッドに依存する問題かもしれません。運悪く私と同じ現象になった人は、アナログ入力で使うと良いでしょう。

 

ハット値

ハット値float val = button . getValue();
float val = hat . getValue();

button : ボタンイスタンス
hat : ハットインスタンス
val : ボタンの値

ハットもボタンの1種なので、ボタンインスタンスの getValue() メソッドで現在値が取得できます。もちろんハットインスタンスからでも取得可能です。どちらも同じ値が戻ってきます。

ハットは8方向の各値と、押していない事  を示す9種類の値を戻します。押していない時は 0 になります。

(画像URL:ELECOM 様 JC-U4013SBK)

.

ハット値Boolean val = hat. up();
Boolean val = hat. down();
Boolean val = hat. left();
Boolean val = hat. right();
Boolean val = hat. pressed();

hat : ハットインスタンス
val : 押されている時 true

ハットが押されているかどうかは、ハットインスタンスの持つメソッドでも検査できます。

up()、down()、left()、right() の各メソッドが true を戻す時、該当方向にボタンが押されています。pressed() は方向に関係なくハット押されている時に true となります。

 

【関連記事】

  • なし

 


サンプルプログラム

シンプルなボタン検出例:

PCに ”JC-U4013S DirectInput Mode” という名前のゲームパッドが接続されていることが条件です。

ボタン0番(JC-U4013Sの場合はX)を押すか、ボタン1番(JC-U4013Sの場合はY)を押すと、コンソールにメッセージが表示されます。

<出力サンプル>

(画像URL:ELECOM 様 JC-U4013SBK)

 

シンプルなスライダー検出例:

PCに ”JC-U4013S DirectInput Mode” という名前のゲームパッドが接続されていることが条件です。

右ステック(JC-U4013Sの場合は0番が右ステックの上下、1番が右ステックの左右)を倒すと、コンソールにメッセージが表示されます。

判定を +0.1 以上や -0.1 以下にしているのは、スティックが真ん中にある場合でも正確に0を示さないことへの対応です。

<出力サンプル>

(画像URL:ELECOM 様 JC-U4013SBK)

 

シンプルなハット検出例:

PCに ”JC-U4013S DirectInput Mode” という名前のゲームパッドが接続されていることが条件です。

JC-U4013S では、ハットはボタンの13番として認識されます。ハットを倒した方向に、赤丸が描かれます。

<出力サンプル>

(画像URL:ELECOM 様 JC-U4013SBK)

 

応用例:

PCに ”Controller (JC-U4013S XInput Mode)” という名前のゲームパッドが接続されていることが条件です。

初期処理で、Dataフォルダからターゲットスコープ用の画像(scope.png)と、爆発エフェクト用の画像(bomb00.png から bomb15.pngまで)を読み込みます。

ゲームパッドの左スティックを動かすと、ターゲットスコープが移動します。Bボタンを押下すると、その時点のスコープ位置に爆発が起きます。

DirectInputモードのゲームパッドでは、左スティックやBボタンでは動作しない可能性があります。その場合は、プログラムに定義してあるスライダー番号やボタン番号の定数を変更して下さい。

<出力サンプル>

(画像URL:HSP3オフィシャル2D素材 様、illust-AC 様:至福の隙間さん)

下記はサンプルプログラムと同じ動きになるように、 P5.js で書き直したものです。動作イメージを確認できます。

なお下記は、 ゲームパッドがPCに接続されていないと動作しません。その関係で、スマホ搭載ブラウザからも正しく表示されません。悪しからずご了承下さい。


(画像URL:HSP3オフィシャル2D素材 様、illust-AC 様:至福の隙間さん)

 


PROCESSING逆引きリファレンス一覧 へ戻る

本ページで利用しているアイコン画像は、下記サイト様より拝借しております。各画像の著作権は、それぞれのサイト様および作者にあります。