#サマリ
結論から申し上げますと、toio™️のキューブをgamepadを使ってラジコン操作出来る、マルチプラットフォームツールを作りましたよと言う話です。動画でまとめるとこんな感じの機能があります。
YouTube -> https://youtu.be/Adt6j601e4E#toio のキューブをブラウザから各種Gamepad(DUALSHOCK 4やJoy-Con)を使ってラジコン操作出来る、マルチプラットフォームツールを作りました。
— Tetsunori NAKAYAMA | 中山 哲法 (@tetunori_lego) February 1, 2020
詳しくは下記Qiita記事にて。https://t.co/2g1W8Jd5RK
ツール↓https://t.co/D4bpq19sAb#WebBluetooth #GamepadAPI pic.twitter.com/liPmep72ft
#成果物
こちらにアクセスするだけで使えます。ソースコードもOSSでどうぞ。
主な特徴
- Windows、Mac対応。Androidはサポートしているはずだが、未確認。(iOS、iPadOSは非対応)
- Dualshock4、Joy-Conを始めとする無線コントローラーやUSBゲームパッド(一部機能限定)に対応
- 複数のラジコン操作方法に対応。2つのキューブを1つのコントローラーから制御する事も可能。
- Joy-Conのセパレートスタイルにも対応。2人でラジコンレースできるよ!
#きっかけ
先日の記事の内容を開発している時、gamepadAPIでJoy-Conなど簡単に使えて大変気持ちが良かったので、単純にラジコン操作出来るツールが欲しくなったまでです。
コントローラーが無線になるだけで、自由度は爆上がりですし。
準備
システム構成
Hardware
- キューブの電源を入れましょう。
- Dualshock 4やJoy-Con(L&R)などのBluetooth/USB gamepadを用意します。特にBluetooth系のコントローラーは事前にPCとペアリング作業を終えてください。
Software
- 冒頭でも紹介したこのツールにアクセスしてください。Google Chromeを強く推奨します。
- GamepadのPS/Homeボタンを押して、画面上のgamepadアイコンが図の様に白く変われば認識できています。(Homeボタン系がないUSBコントローラー等はSELECT/START同時押しで代用です。)
- それと同時にキューブを接続するためのウィンドウが立ち上がりますので、キューブを選択して接続してください。ダイアログ閉じちゃった場合などは手動で"Connect Cube 1/2"ボタンを押して一つずつ接続してください。
- 全ての準備が上手くいけば、下記の様な画面に遷移していると思います。これで準備は完了です!
各種モードについて
シンプルツールですとか言っておきながら、色んな操作モード作って複雑にしてしまったので図にしました。
少しテキストでフォローすると、ざっくり以下の使い分けになっています。
- Single Cube Control(1つのgamepad で1つのキューブを操作)
- Double Cube Control(1つのgamepad で2つのキューブを操作)
画面仕様
Single Cube Control
## Double Cube Control操作方法
全てに共通
カテゴリ | Gamepad操作 DUALSHOCK 4/Joy-Con |
UI例 |
---|---|---|
Cube1/2の切り替え | OPTION/‘+’ button | Cube1は水色に、Cube2は緑色にそれぞれ光ります |
設定リセット | PS/HOME button | USB gamepadの場合はSTART+SELECT同時押しで代用 |
スピード調整 | L1/R1, L/R button | デフォルト値は60 |
Single Cube Control
モード共通
カテゴリ | Gamepad操作 DUALSHOCK 4/Joy-Con |
UI例 |
---|---|---|
gamepadの登録 | PS/Home button | 未登録な場合 |
gamepad1/2の切り替え | PS/Home button | 登録済みの場合 |
操作モードの切り替え | SHARE/‘-‘ button | Normal<->Stickをトグルします |
Double Cube Controlへの切り替え | PS/Home button長押し | - |
Normal mode
Stick mode
カテゴリ | Gamepad操作 DUALSHOCK 4/Joy-Con |
UI例 |
---|---|---|
スピードコントロール | Y-axis of left analog stick or left/right trigger | UP/DOWN buttonも最速設定として使用できます |
方向コントロール | X-axis of right analog stick | CIRCLE/A, SQUARE/Y buttonも最大値として使えます |
Working demo movie(will update...) |
Double Cube Control
モード共通
カテゴリ | Gamepad操作 DUALSHOCK 4/Joy-Con |
UI例 |
---|---|---|
操作モードの切り替え | SHARE/- button | Combined<->Separatedとトグルします |
Single Cube Controlへ切り替え | PS/Home button | 戻る時は単押しでオッケーです |
Combined mode
Separated mode
SWのポイント
gamepadを振動させるには
今回gamepad1/2に登録・切り替えする際にgamepadを振動させています。Daulshock 4やJoy-Conで体験できます。
振動デバイスが異なる両者ですが、どちらも同一ソースコードで動きます。
const _vibrateGamePad = ( gamePad, duration ) => {
if ( gamePad.vibrationActuator ) {
gamePad.vibrationActuator.playEffect( "dual-rumble", {
duration: duration,
weakMagnitude: 1.0,
strongMagnitude: 1.0
} );
}
}
それぞれ良いところがありますがJoy-Conのhapticはキレが良くて好きですね。
※Android Chromeでは振動非サポートの様。
gamepadのdescriptionを取得する
gamepadが接続された時に機種名を表示していますが、Daulshock 4(1st/2nd gen)やJoy-Conが接続された時のみ特別な表記にしています。特に理由はありませんが。。。
取得や判別は容易でgamepad.id
にアクセスするだけです。
const getDescription = ( index ) => {
let description;
const gamepad = navigator.getGamepads()[ /* gamepad index */ ];
if( gamepad ){
if( isJoyCon( index ) ){
description = 'Joy-Con L+R';
}else if( isDualShock4_1stGen( index ) ){
description = 'DUALSHOCK 4(1st Gen)';
}else if( isDualShock4_2ndGen( index ) ){
description = 'DUALSHOCK 4(2nd Gen)';
}else{
description = gamepad.id;
}
}
return description;
}
const isDualShock4_2ndGen = ( gamepadIdx ) => {
const gamepad = navigator.getGamepads()[ /* gamepad index */ ];
if( gamepad ){
const gamepadDesc = gamepad.id;
if( gamepadDesc.indexOf('Wireless Controller (STANDARD GAMEPAD Vendor: 054c Product: 09cc)') !== -1 ){
return true;
}else{
return false;
}
}else{
return false;
}
}
USBコントローラの注意点
市販されているUSBコントローラーはボタンの数が少ないものもあるため、Button 10以降は無いものが多かったです。これらは無くても動作するように設計すべきでした。今回は実装した後に気が付いてしまったので、work aroundで乗り切りました。
const gamePad = navigator.getGamepads()[ idGamepad ];
const GAMEPAD_BT_HOME = 16;
const GAMEPAD_BT_8 = 8;
const GAMEPAD_BT_9 = 9;
let currentHomeButtonStatus;
if( gamePad.buttons[ GAMEPAD_BT_HOME ] ){
currentHomeButtonStatus = gamePad.buttons[ GAMEPAD_BT_HOME ].value;
}else{
currentHomeButtonStatus = gamePad.buttons[ GAMEPAD_BT_8 ].value &&
gamePad.buttons[ GAMEPAD_BT_9 ].value;
}
動作確認済機器
PC
- OK: Windows10 Home / vaio VJP132
- 未: Mac、、、はどなたか確認してもらえないかなぁ。
- NG: Android 8.0.0 / SOV34
- OS側に取られているのか、Chrome側にはgamepad制御権回ってこなかった?
- OK: Android 6.0.1 / vaio phone VPA051
gamepad
- OK: [Bluetooth] Dualshock 4 (1st gen.)
- OK: [Bluetooth] Dualshock 4 (2nd gen.)
- OK: [Bluetooth] Joy-Con
- OK: [USB] iBUFFALO BSGP801
- OK: [USB] 『プレイステーション クラシック』同梱USBコントローラー
所感と考察
- gamepad APIは簡単に扱えるのは良いが、思ったよりgamepad機種(ボタン配置)差分があって、その辺をケアするのは大変ですね
- Androidでもう少しすんなり使えるかなーと思いましたが、スマホのUI操作の方に優先権があるのは致し方ないか。選択権があると良いのにな。
- いろんなプロトタイプに使ってもらえると幸いです。