DS4の値をプログラムで取得
HSPでジョイスティックを使うサンプルを作りました
DUALSHOCK4の値を取得と行っても、加速度やタッチパッドの入力が取得できるわけではありません。
あくまで標準ドライバで動作するゲームコントローラとして取得できる値を取得するサンプルです。
HSPでのジョイスティック(ゲームコントローラ)の動作確認と使い方が確認できるサンプルを作ってみました。
DUALSHOCK4に限らずWindowsでゲームコントローラと認識されていれば何でも使えます。
DUALSHOCK4のアナログ値を6個ともちゃんと取得できますし、PSボタンやタッチパッド押下も検出できます。
DUALSHOCK4はL2/R2とアナログが連動していて、ちょっと変則的な動作をしますが第5,6軸を使うゲームはフライトシミュ以外では殆ど存在しないと思うので通常のゲームには影響ないと思います。
サンプル
標準ドライバで取得できるすべての情報を取得するので、joyGetPosEx命令を使用します。
ジョイスティックが反応しない場合、環境に合わせてuJoyIDの値を書き換えて使ってください。
;
; joyGetPosEx を使ったサンプル
;
#include "mod_joystick.as"
dim data, 13
; ジョイスティックID(0~)
;値を拾わない場合はこの値を+1ずつ変更してみてください。
uJoyID = 0
*main
redraw 1 : await 16 : redraw 0 : color 255, 255, 255 : boxf : color : pos 0,0
;-------------------------
; コントローラの値を取得
;-------------------------
joyGetPosEx data, uJoyID
;-------------------------
; 取得した値をそのまま表示
;-------------------------
pos 10, 10
repeat 13
mes strf("(%2d) : ", cnt) + data(cnt)
loop
;-------------------------
; ボタンの状態(最大32ボタン)
;-------------------------
;状態の取り出し方の例
pos 150, 10
mes "data(8) = " + data(8)
mes "(同時押し " + data(9) + " 個)"
if data(8) & 0x00000001 : mes "0x00000001" : else : mes "-"
if data(8) & 0x00000002 : mes "0x00000002" : else : mes "-"
if data(8) & 0x00000004 : mes "0x00000004" : else : mes "-"
if data(8) & 0x00000008 : mes "0x00000008" : else : mes "-"
if data(8) & 0x00000010 : mes "0x00000010" : else : mes "-"
if data(8) & 0x00000020 : mes "0x00000020" : else : mes "-"
if data(8) & 0x00000040 : mes "0x00000040" : else : mes "-"
if data(8) & 0x00000080 : mes "0x00000080" : else : mes "-"
if data(8) & 0x00000100 : mes "0x00000100" : else : mes "-"
if data(8) & 0x00000200 : mes "0x00000200" : else : mes "-"
if data(8) & 0x00000400 : mes "0x00000400" : else : mes "-"
if data(8) & 0x00000800 : mes "0x00000800" : else : mes "-"
if data(8) & 0x00001000 : mes "0x00001000" : else : mes "-"
if data(8) & 0x00002000 : mes "0x00002000" : else : mes "-"
if data(8) & 0x00004000 : mes "0x00004000" : else : mes "-"
if data(8) & 0x00008000 : mes "0x00008000" : else : mes "-"
if data(8) & 0x00010000 : mes "0x00010000" : else : mes "-"
if data(8) & 0x00020000 : mes "0x00020000" : else : mes "-"
if data(8) & 0x00040000 : mes "0x00040000" : else : mes "-"
if data(8) & 0x00080000 : mes "0x00080000" : else : mes "-"
;取り敢えず20個まででやめておきます。
;同様のやり方で全32ボタンまで検出できます。長くなる上に現実的ではないので省略。
; ボタンの状態を2進数で表示
;data(8)の中の動きの意味は、2進数表示すると分かりやすくなります。
;さらにビット演算の意味がわかると、自在に状態を取り出せるようになります。
s=""
repeat 32
s = str((data(8) & 1<<cnt)!0) + s
loop
mes s
;-------------------------
; POVの状態
;-------------------------
;ハットスイッチとよばれることもあります。
; x100度を返します。度単位なのでわかりやすいですが、意外と扱いが面倒です。
pos 300, 10
mes "data(10) = " + data(10)
mes "POVスイッチ"
pov = data(10)
if (pov & 0xFFFF)!0xFFFF {
; なにか押されていた場合の処理
;povは何も押されていない場合、環境によって-1を帰す場合と、0xFFFFを帰す場合があります。
;↑方向を 0度とした角度[deg]を返します。
;値は100倍されたものを返します。右回り正。
;→方向は 9000
;↓方向は18000
;←方向は27000
;↑+→方向は4500となります。
if (pov=31500)|(pov= 0)|(pov= 4500) : mes "↑"
if (pov= 4500)|(pov= 9000)|(pov=13500) : mes "→"
if (pov=13500)|(pov=18000)|(pov=22500) : mes "↓"
if (pov=22500)|(pov=27000)|(pov=31500) : mes "←"
}
;-------------------------
; アナログ
;-------------------------
;6軸あります。通常のコントローラの場合、アナログ入力なしか実装されていても4軸までです。
;0~65535の値を取ります。
pos 450, 10
mes "アナログ"
repeat 6
x0 = 450 + cnt * 5
x1 = x0 + 3
y0 = 30
y1 = y0 + data(2+cnt)/200
boxf x0,y0, x1,y1
loop
goto *main
解説
見たら分かるような気もしますが…。
ボタンの検出は基本的にビット演算が理解できるようになれば、扱いが簡単です。ビット演算を理解しましょう。
サンプルではボタン20個までしか値を拾わないようにしていますが、32ボタンまで検出可能です。32ボタンてどんなコントローラなんでしょうね。
POVはハットスイッチとか十字キーとか呼ばれます。コントローラによっては十字キー押すとアナログスティックとして検出されるものもあってややこしいところではあります。
POVの値は上を0度として右回りの度数法で検出されます。一見わかりやすいように見えますが、プログラムする上では処理がめんどくさくて困りますね。
アナログ入力は仕様上、6軸まで検出できます。検出できる値は、0~65535 = 0x0~0xFFFF。つまり2バイト=16bitで量子化されています。
6軸まで検出できるのですが、普通のゲームコントローラだと、そもそもアナログ入力が無かったり、多くても4軸(2軸のスティックが2本)だったりします。
第5,6軸が実装されているコントローラはフライトシミュレーションゲーム用の操縦桿型コントローラとDUALSHOCK4ぐらいだと思います。
尚、アナログ入力がないゲームコントローラは十字キーを押すとアナログスティックを操作したのと同じ値が出るようです。POVに見えてもPOVじゃない。
こういった実装事情を考慮して、プログラムされることをおすすめします。
もっと使いやすくするモジュール
DUALSHOCK4について確認したところ、私が昔作成したモジュールPAD設定さんでも正常に値取得などができるようです。
モジュール付属のサンプルでは動作確認できませんが、サンプルを少しいじるだけでOKです。
詳しい使い方はまた後ほど。