◆PROCESSING 逆引きリファレンス
カテゴリー:ゲーム作成
ゲームパッドを使うには
【概要】
PROCESSINGはマウスやキーボードからの入力を手軽に扱うことができて便利なのですが、ゲームなどではゲームパッドからの入力を扱いたいことがあります。
残念ながらPROCESSINGの標準命令だけではゲームパッドは扱えません。しかしPROCESSINGには、このような用途に適した Game Control Plus ライブラリがあります。
今回はGame Control Plus ライブラリを使ってゲームパッドからの入力を受け取る方法について紹介したいと思います。
なおGame Control Plus ライブラリについては、以下のサイト様などが参考となります。私も大いに参考とさせていただきました。ありがとうございます。
- Processingでゲームパッドを使おう 雑念日記 様
- 【P5 Tips】 ProcessingをNintendo SwitchのJoy-Conで遠隔操作する note 様
- 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 インスタンス
1 2 3 4 |
void setup(){ // インスタンスを取得する ControlIO control = ControlIO.getInstance(this); } |
ControlIO の staticメソッドである getInstance() でインスタンスを取得します。インスタンスの取得は簡単ですね。
デバイスを取得する
ControlDevice device = control . getDevice (String deviceName);
deviceNumber : ゲームパッドの番号
deviceName : ゲームパッドのデバイス名
control : ControlIO インスタンス
device : デバイスインスタンス
1 2 3 4 5 6 7 8 9 10 11 12 13 |
void setup(){ // インスタンスを作成する ControlIO control = ControlIO.getInstance(this); // デバイスを取得する String devName = "JC-U4013S DirectInput Mode"; try{ ControlDevice device = control.getDevice( devName ); } catch( RuntimeException e ){ // 存在しない場合など e.printStackTrace(); } } |
ControlIOのインスタンスを取得したら、デバイスを取得します。
デバイスを取得するには、あらかじめ対象となるデバイスの名前もしくは番号がわかっている必要があります。デバイスの名前は、前述の手順で事前に調べておくことになります。
上記例では、デバイスの名前を指定して取得しています。デバイスが見つからないとRuntimeException が発生するので注意してください。
デバイスをOPENする
device : デバイスインスタンス
1 2 3 4 5 6 7 8 9 10 11 |
void setup(){ // インスタンスを作成する ControlIO control = ControlIO.getInstance(this); // デバイスを取得する String devName = "JC-U4013S DirectInput Mode"; ControlDevice device = control.getDevice( devName ); // OPEN する device.open(); } |
デバイスが取得できたらOPENします。
デバイス一覧を得る
それではデバイス名が不明な場合や、デバイス名が文字化けしていて指定できない場合は、どうすれば良いでしょうか?
ControlIOクラスには、ライブラリが認識しているデバイスの一覧を取得するgetDevices()メソッドがあります。
.
control : ControlIO インスタンス
devList : デバイス一覧
このメソッドでデバイスの一覧を取得し、デバイスの種類がゲームパッドのものを取り出す事で対応する方法が考えられます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
void setup(){ // インスタンスを作成する ControlIO control = ControlIO.getInstance(this); // デバイス一覧を取得する ControlDevice device; List<ControlDevice> devList = control.getDevices(); // デバイス一覧から、最初のGamePadを取得する for( ControlDevice dev : devList){ if( dev.getTypeName() .equals(Controller.Type.GAMEPAD.toString())){ // GamePadを見つけた device = dev; break; } } if (device == null) { // 見つからねーじゃん... println("ERROR: No available devices found."); exit(); return; } // OPENする device.open(); } |
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つの関数としてまとめた方が良いでしょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
ControlIO control; ControlDevice device; ControlButton[] buttons; ControlSlider[] sliders; // 取得対象デバイス候補となるタイプの一覧 List<String> deviceTypeCandidates = new ArrayList<String>() { { add(Controller.Type.STICK.toString()); add(Controller.Type.FINGERSTICK.toString()); add(Controller.Type.GAMEPAD.toString()); } }; Boolean openDevice(){ // インスタンスを作成する control = ControlIO.getInstance(this); // デバイス一覧からGamePadを取得する for( ControlDevice dev : control.getDevices()){ if (deviceTypeCandidates.contains(dev.getTypeName())) { // GamePadを見つけた device = dev; break; } } if (device == null) { println("ERROR: No available devices found."); return false; } // OPENする device.open(); return true; } |
ボタン、スライダー、ハットを取得する
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 : デバイスインスタンス
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
ControlIO control; ControlDevice device; void setup(){ // デバイスをOPENする openDevice(); // スライダーを取得する ControlSlider slider = device.getSlider( 0 ); if( slider == null ){ println("ERROR: No available slider 0 found."); } // ハットを取得する ControlHat hat = device.getHat( 13 ); if( hat == null ){ println("ERROR: No available hat 0 found."); } // ボタンを取得する ControlButton button = device.getButton( 0 ); if( button == null ){ println("ERROR: No available button 0 found."); } } |
上記例の openDevice() は、上で説明したデバイスをOPENする処理をまとめた関数です。
名前または番号を指定して、ボタンオブジェクト、ハットオブジェクト、スライダーオブジェクトを取得します。それぞれの名前や番号は、前述の手順で事前に調べておくことになります。
ボタンとスライダー数を取得する
int sliderNum= device. getNumberOfSliders();
buttonNum : ボタン数
sliderNum : スライダー数
device : デバイスインスタンス
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
ControlIO control; ControlDevice device; void setup(){ // デバイスをOPENする openDevice(); // ボタンとスライダー数を取得する int buttonNum = device.getNumberOfButtons(); int sliderNum = device.getNumberOfSliders(); println( "このGamePadには\n" + buttonNum + "個のボタン\n" + sliderNum + "個のスライダー\n" + "が接続されています" ); } |
該当ゲームパッドに搭載されているボタン数とスライダー数を取得します。ハットの数を取得する命令は無いようです。
注意としては、ハットがボタンとして数えられる事です。私が持っている JC-U4013S では、そのようになりました。
正確にボタンの数だけ(あるいはハットの数だけ)知りたい場合は、ボタンインスタンスを0番から getNumberOfButtons() 数まで取得し、該当ボタンインスタンスのクラス名を見るしかなさそうです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
ControlIO control; ControlDevice device; void setup(){ // デバイスをOPENする openDevice(); // ボタン数を取得する int buttonNum = device.getNumberOfButtons(); // クラス名でボタンとハットを識別する int hatNumber = -1; for( int index = 0; index < buttonNum; index++){ // クラス名で判別する String className = device.getButton( index ).getClass().toString(); if( className.indexOf("Hat") > -1){ // ハットの場合 println( index + "番目はHatのようです。" ); hatNumber = index; } } // Hatを取得する if(hatNumber > -1){ ControlHat hat = device.getHat( hatNumber ); } } |
例えば上記では、CLass名でハットかボタンかを識別し、Hatの番号を得て、ハットインスタンスを取得しています。なんかダサイですけど・・・他に良い方法が見つかりませんでした。
ボタンイベント
button : ボタンインスタンス
obj: イベントを受け取るクラス。通常は this
methodName : イベントを受け取るメソッド名
eventType : イベントの種類。ON_PRESS, ON_RELEASE, WHILE_PRESS
ボタンには、押した時(ON_PRESS)、離した時(ON_RELEASE)、押しっぱなしの時(WHILE_PRESS)に対応するイベントを定義できます。
それぞれ ControlIO クラスの定数で指定します。
メソッド名には、該当イベントを受け取る「 void型で、引数なし」のメソッド名を指定します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
ControlIO control; ControlDevice device; int whileCount; void setup(){ // デバイスをOPENする openDevice(); // ボタンを取得する ControlButton button = device.getButton( 0 ); // イベントをセットする // 押した button.plug( this, "pressButton", ControlIO.ON_PRESS); // 離した button.plug( this, "releaseButton", ControlIO.ON_RELEASE); // 押している button.plug( this, "whileButton", ControlIO.WHILE_PRESS); } // 押したイベント受け取り用メソッド void pressButton(){ println("ボタンが押されました"); whileCount = 0; } // 離したイベント受け取り用メソッド void releaseButton(){ println("ボタンが離されました"); println( whileCount + "回押されていました"); } // 押されっぱなしイベント受け取り用メソッド void whileButton(){ whileCount += 1; println("ボタンが押されています" + whileCount ); } |
こんな感じですね。
plug() で指定したメソッド名に一致するメソッドが見つからない場合や、引数の数が一致しない場合(引数ありのメソッドを指定した場合)は、実行時に例外が発生するので注意してください。
またリファレンス上ではハットにも同様のイベントを定義できることになっていますが、手持ちの JC-U4013S では例外エラーとなってしまいました。
ゲームパッドによっては、ハットにはイベントを定義できないようですので注意してください。
ボタン押下判定
button : ボタンインスタンス
pressed : 押されている時 true
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
ControlIO control; ControlDevice device; ControlButton button; void setup(){ size(300,300); // デバイスをOPENする openDevice(); // ボタンを得る button = device.getButton( 0 ); } void draw(){ if( button.pressed()){ println("0番のボタンが押されています"); } } |
その瞬間にボタンが押されているかどうかは、ボタンクラスの pressed() メソッドで判定可能です。
presswd() メソッドを draw() 関数などから適当に検査すれば、その瞬間のボタンの挙動を判定できます。
スライダー値
slider : スライダーインスタンス
val : スライダーからの値
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
ControlIO control; ControlDevice device; ControlSlider slider; void setup(){ size(300,300); // デバイスをOPENする openDevice(); // スライダーを取得する slider = device.getSlider( 0 ); println( "スライダー値は" + slider.getMultiplier() + "~" + slider.getTolerance() + "と" + -1 * slider.getMultiplier() + "~" + slider.getTolerance() + "まで変化します。" ); } void draw(){ // スライダーの現在値を表示する println( slider.getValue() ); } |
スライダーインスタンスの getValue() メソッドで、該当スライダーの現在値を取得できます。
スライダー値は、スライダーの傾斜に伴い変化します。スライダー値が変化する範囲は、getMultiplier() と getTolerance() で取得できます。
JC-U4013S では、getMultiplier() は +1.0 を、getTolerance() は 0.0 を返します。したがって値の変化する範囲は、+getMultiplier() から getTolerance()と、-getMultiplier() から getTolerance() になります。
getMultiplier() が 1.0、getTolerance() が 0.0 の場合、左右スライダーなら 真左が -1.0、真右は +1.0 、上下スライダーなら真上が -1.0、真下は +1.0 になります。
(画像URL:ELECOM 様 JC-U4013SBK)
ただしスライダーが真ん中(静止状態)にあっても、正確に 0 を示さない事があるので注意してください(0に近い値にはなります)。
また一部のゲームパッドでは、デジタル入力時においてスライダーから変化値を拾えない事があるようです。
なにかの不具合っぽい感じがしますが、ゲームパッドに依存する問題かもしれません。運悪く私と同じ現象になった人は、アナログ入力で使うと良いでしょう。
ハット値
float val = hat . getValue();
button : ボタンイスタンス
hat : ハットインスタンス
val : ボタンの値
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
ControlIO control; ControlDevice device; ControlButton button; ControlHat hat; void setup(){ size(300,300); // デバイスをOPENする openDevice(); // ハットを取得する(どちらでもOK) //button = device.getButton( 13 ); hat = device.getHat( 13 ); } void draw(){ // ハットの現在値を表示する //println( button.getValue() ); println( hat.getValue() ); } |
ハットもボタンの1種なので、ボタンインスタンスの getValue() メソッドで現在値が取得できます。もちろんハットインスタンスからでも取得可能です。どちらも同じ値が戻ってきます。
ハットは8方向の各値と、押していない事 を示す9種類の値を戻します。押していない時は 0 になります。
(画像URL:ELECOM 様 JC-U4013SBK)
.
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 となります。
【関連記事】
- なし
サンプルプログラム
シンプルなボタン検出例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
import net.java.games.input.*; import org.gamecontrolplus.*; import org.gamecontrolplus.gui.*; /** * PROCESSING 3 GamePad Sample * @auther MSLABO * @version 2018/10 1.0 */ ControlIO control; ControlDevice device; ControlButton button_0; ControlButton button_1; // デバイス名(あなたの環境に合わせて変更要) final String DEVNAME = "JC-U4013S DirectInput Mode"; void setup(){ size( 300,300 ); textAlign(LEFT,TOP); textSize(16); // インスタンスを作成する control = ControlIO.getInstance(this); // デバイスを取得する device = control.getDevice( DEVNAME ); // OPEN する device.open(); // ボタンを取得する button_0 = device.getButton( 0 ); button_1 = device.getButton( 1 ); //ボタン1に押下イベント登録 button_1.plug( this, "pressButton01", ControlIO.ON_PRESS); } void draw(){ //ボタン0の押下状態検査 if( button_0.pressed()){ println("0番のボタンが押されています"); } } //ボタン1が押されたイベント void pressButton01(){ println("1番のボタンが押されました"); } |
PCに ”JC-U4013S DirectInput Mode” という名前のゲームパッドが接続されていることが条件です。
ボタン0番(JC-U4013Sの場合はX)を押すか、ボタン1番(JC-U4013Sの場合はY)を押すと、コンソールにメッセージが表示されます。
<出力サンプル>
(画像URL:ELECOM 様 JC-U4013SBK)
シンプルなスライダー検出例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
import net.java.games.input.*; import org.gamecontrolplus.*; import org.gamecontrolplus.gui.*; /** * PROCESSING 3 GamePad Sample * @auther MSLABO * @version 2018/10 1.1 */ ControlIO control; ControlDevice device; ControlSlider slider_0; ControlSlider slider_1; // デバイス名(あなたの環境に合わせて変更要) final String DEVNAME = "JC-U4013S DirectInput Mode"; void setup(){ size( 300,300 ); textAlign(LEFT,TOP); textSize(16); // インスタンスを作成する control = ControlIO.getInstance(this); // デバイスを取得する device = control.getDevice( DEVNAME ); // OPEN する device.open(); // スライダーを取得する slider_0 = device.getSlider( 0 ); slider_1 = device.getSlider( 1 ); } void draw(){ //スライダーの押下状態検査 //JC-U4013SBKでは0番は上下スライダー if( slider_0.getValue() < - 0.1 ){ println( "スライダー0番は上に倒されています"); } else if( slider_0.getValue() > 0.1 ){ println( "スライダー0番は下に倒されています"); } //JC-U4013SBKでは1番は左右スライダー if( slider_1.getValue() < - 0.1 ){ println( "スライダー1番は左に倒されています"); } else if( slider_1.getValue() > 0.1 ){ println( "スライダー1番は右に倒されています"); } } |
PCに ”JC-U4013S DirectInput Mode” という名前のゲームパッドが接続されていることが条件です。
右ステック(JC-U4013Sの場合は0番が右ステックの上下、1番が右ステックの左右)を倒すと、コンソールにメッセージが表示されます。
判定を +0.1 以上や -0.1 以下にしているのは、スティックが真ん中にある場合でも正確に0を示さないことへの対応です。
<出力サンプル>
(画像URL:ELECOM 様 JC-U4013SBK)
シンプルなハット検出例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 |
import net.java.games.input.*; import org.gamecontrolplus.*; import org.gamecontrolplus.gui.*; /** * PROCESSING 3 GamePad Sample * @auther MSLABO * @version 2018/10 1.2 */ ControlIO control; ControlDevice device; ControlButton hat; // デバイス名(あなたの環境に合わせて変更要) final String DEVNAME = "JC-U4013S DirectInput Mode"; // ハット番号(あなたの環境に合わせて変更要) final int HATNUM = 13; void setup(){ size( 300,300 ); textAlign(LEFT,TOP); textSize(16); // インスタンスを作成する control = ControlIO.getInstance(this); // デバイスを取得する device = control.getDevice( DEVNAME ); // OPEN する device.open(); // ハットを取得する hat = device.getButton( HATNUM ); } void draw(){ background( 128 ); //ハットの押下状態検査 //8角形を描く noFill(); pushMatrix(); translate(width/2, height/2); beginShape(); for (int i = 0; i < 8; i++) { vertex( 100*cos(radians(360*i/8)), 100*sin(radians(360*i/8))); } endShape(CLOSE); popMatrix(); fill(0); //ハットの値を得る float deg = -1; float val = hat.getValue(); //ハットの位置を角度に変換 switch((int)val){ case 1: deg = 225; break; case 2: deg = 270; break; case 3: deg = 315; break; case 4: deg = 0; break; case 5: deg = 45; break; case 6: deg = 90; break; case 7: deg = 135; break; case 8: deg = 180; break; } //ハットの位置に赤丸を描く float cx = width/2; float cy = height/2; if( deg > -1 ){ cx = width/2 + 100*cos(radians(deg)); cy = height/2 + 100*sin(radians(deg)); } fill(255,0,0); ellipse( cx,cy,16,16); } |
PCに ”JC-U4013S DirectInput Mode” という名前のゲームパッドが接続されていることが条件です。
JC-U4013S では、ハットはボタンの13番として認識されます。ハットを倒した方向に、赤丸が描かれます。
<出力サンプル>
(画像URL:ELECOM 様 JC-U4013SBK)
応用例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
import net.java.games.input.*; import org.gamecontrolplus.*; import org.gamecontrolplus.gui.*; import java.awt.Point; /** * PROCESSING 3 GamePad Sample * @auther MSLABO * @version 2018/10 1.4 */ // デバイス名と部品番号(あなたの環境に合わせて変更要) final String DEVNAME = "Controller (JC-U4013S XInput Mode)"; final int Y_BUTTON = 1; //Yボタン番号 final int LEFT_SL_BU = 0; //左上下スライダー番号 final int LEFT_SL_RF = 1; //左左右スライダー番号 //変数 ControlIO control; ControlDevice device; ControlButton buttonY; ControlSlider leftRl; ControlSlider leftBu; PImage scopeImg; //スコープ画像 PImage[] bombImg; //爆発エフェクト画像 int scopeX, scopeY; //スコープ位置 clFirePoint[] firePoint; //爆発エフェクト管理クラス配列 // 爆発エフェクト管理クラス class clFirePoint { Point toPoint; //座標 int frameIndex; //アニメ画像番号 boolean dispFlg; //表示中FLG // コンストラクタ public clFirePoint( int x, int y ){ toPoint = new Point( x, y ); dispFlg = false; frameIndex = 0; } } void setup(){ size( 400,300 ); frameRate(60); // 画像読み込み scopeImg = loadImage("scope.png"); bombImg = new PImage[16]; for( int i = 0; i < 16; i++){ bombImg[i] = loadImage("bomb" + nf(i,2) + ".png"); } // インスタンスを作成する control = ControlIO.getInstance(this); // デバイスを取得する device = control.getDevice( DEVNAME ); // OPEN する device.open(); //各部品を取得する buttonY = device.getButton( Y_BUTTON ); buttonY.plug(this, "btnYPressed", ControlIO.ON_PRESS); leftRl = device.getSlider( LEFT_SL_RF ); leftBu = device.getSlider( LEFT_SL_BU ); //スコープ座標を初期化 scopeX = (width - scopeImg.width)/2; scopeY = (height - scopeImg.height)/2; //爆発エフェクト管理クラスを生成 firePoint = new clFirePoint[32]; for( int i = 0; i < 32; i++ ){ firePoint[i] = new clFirePoint(0,0); } } void draw(){ background(0); //爆発エフェクト表示 drawFire(); //スライダーの位置にスコープを描く int slValX = (int)map( leftRl.getValue(), -1, 1, -45, width - scopeImg.width/2 ); int slValY = (int)map( leftBu.getValue(), -1, 1, -45, height - scopeImg.height/2 ); image( scopeImg, slValX, slValY ); } // Yボタン押下イベント void btnYPressed(){ //ボタンを押したときのスライダー位置に //爆発エフェクト情報をセットする int slValX = (int)map( leftRl.getValue(), -1, 1, -45, width - scopeImg.width/2 ); int slValY = (int)map( leftBu.getValue(), -1, 1, -45, height - scopeImg.height/2 ); for( int i = 0; i < 32; i++ ){ //非表示箇所を見つけた if( firePoint[i].dispFlg == false){ firePoint[i].toPoint.x = slValX; firePoint[i].toPoint.y = slValY; firePoint[i].frameIndex = 0; firePoint[i].dispFlg = true; break; } } } void drawFire(){ //爆発エフェクト表示 for( int i = 0; i < 32; i++ ){ if( firePoint[i].dispFlg ){ //表示すべきエフェクトを見つけた Point p = firePoint[i].toPoint; image( bombImg[firePoint[i].frameIndex], p.x, p.y ); firePoint[i].frameIndex++; if( firePoint[i].frameIndex > 15 ){ //表示終了 firePoint[i].dispFlg = false; } } } } |
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 様:至福の隙間さん)
本ページで利用しているアイコン画像は、下記サイト様より拝借しております。各画像の著作権は、それぞれのサイト様および作者にあります。