【完走賞ゲット-13】p5.js Web Editor上でボールが跳ね返る時に DualShock 4 を振動させる（gamecontroller.js での実装）

## はじめに
こちらは、[完走賞ゲットのため小ネタを毎日投稿しようとチャレンジする Advent Calendar 2022](https://qiita.com/advent-calendar/2022/youtoy) の 13日目の記事です。

内容は、以下の記事でも扱った「gamecontroller.js と DualShock 4」の組み合わせの話です。今回は、コントローラーを振動させる処理を使ってみます。

- [【完走賞ゲット-10】gamecontroller.js を使って DualShock 4 を JavaScript で扱う - Qiita](https://qiita.com/youtoy/items/87c1c37b51ae9ef4ab4d)
- [【完走賞ゲット-11】gamecontroller.js を p5.js Web Editor上で使ってみる（DualShock 4 との組み合わせ） - Qiita](https://qiita.com/youtoy/items/1cf1fe244d992456140f)

## できあがったもの
今回は、先にできあがったものを掲載してみます。

動画からはちょっと分かりにくいかもしれないですが、奧にある p5.js Web Editor のキャンバス上では白いボールが上下移動しています。そして、上下の端にあたると方向転換するようにしているのですが、その方向転換のタイミングで Dualshock 4 が振動しているという動作になっています。

https://twitter.com/youtoy/status/1602111709283774464

## 実装した内容
### 用いたライブラリ
今回の仕組みは、ブラウザから Dualshock 4　を制御しており、仕組みとしては [Gamepad API](https://developer.mozilla.org/ja/docs/Web/API/Gamepad_API/Using_the_Gamepad_API) を使っています。そして、その API を直接使っているのではなく、[gamecontroller.js](https://github.com/alvaromontoro/gamecontroller.js) というライブラリを用いました。

最初の部分でも掲載した、ここ最近書いた記事（1人アドベントカレンダーの [10日目の記事](https://qiita.com/youtoy/items/87c1c37b51ae9ef4ab4d)と [11日目の記事](https://qiita.com/youtoy/items/1cf1fe244d992456140f)）でも使っています。

### ライブラリの公式サンプル
なお、そのライブラリの GitHub のページを見ていくと、リポジトリの中のファイルで以下のコントローラーを振動をさせるサンプルもありました。

●gamecontroller.js/example-8-vibration.html at master · alvaromontoro/gamecontroller.js · GitHub
　https://github.com/alvaromontoro/gamecontroller.js/blob/master/examples/example-8-vibration.html

内容をざっくり読んでいくと、[72行目あたり](https://github.com/alvaromontoro/gamecontroller.js/blob/master/examples/example-8-vibration.html#L72)の処理を使えば良さそうです。
![公式サンプルでの振動をさせる処理](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/90b31f6b-5bce-d493-7dc3-0dddd00bc76f.png)

過去の記事で使った時の処理内容も合わせ、プログラムを書いてみました。

### 自分が作ったプログラムと動作させる方法
p5.js Web Editor　の sketch.js を、以下のようにして動かしてみました。

```javascript:sketch.js
let gamepad;
let y, vY;
const size = 50;

function setup() {
  createCanvas(450, 350);

  gameControl.on("connect", (_gamepad) => {
    gamepad = _gamepad;
    console.log("A new gamepad was connected!");
  });

  vY = 5;
  y = height / 2;
}

function draw() {
  if (gamepad) {
    background(100);
  } else {
    background(220);
  }

  const x = width / 2;
  y += vY;
  if (y > height - size / 2 || y < 0 + size / 2) {
    vY *= -1;

    if (gamepad) {
      console.log("vibrate");
      gamepad.vibrate(1.0, 150);
    }
  }

  circle(x, y, size);
}
```

冒頭に書いていた動作に加え、DualShock 4 が接続されているかどうかによって、背景の色を変える処理も実装しています。DualShock 4 の接続は USB接続なのですが、それを認識させるためには USB でコントローラーをつないだあとに、コントローラーのどれかのボタンを押せば OK です。

簡単にコントローラーを振動させる処理を使えましたが、振動によるフォースフィードバックが手軽にできるのは夢が広がります。

## おわりに
DualShock 4 を手に入れて、Gamepad API のテストサイト（以下のツイートに出てくるもの）で動かしてみてから、この2つの組み合わせにハマってしまいました 笑

https://twitter.com/youtoy/status/1601361942098350080

引き続き、この DualShock 4 をブラウザで使ってみるシリーズは、何か思いついたら実装してみて記事を書いてみようと思います。

### 当初の予定は...
こちらの記事、MIDI用ノードを使いましたが、当初は HID用のノード [node-red-contrib-usbhid](https://flows.nodered.org/node/node-red-contrib-usbhid) を使おうとしてました。

https://twitter.com/youtoy/status/1602396061968269312

今回使ったフットスイッチは、HIDモードと MIDIモードの切り替えができ、自分が最初に利用していたモードが HID のほうだったためです。
しかし、node-red-contrib-usbhid の追加時にエラーが出て、解決法を探ろうかとも思ったのですがハマるリスクを避けたかったのがあり、過去の自分の利用実績があった MIDI用ノードを使う流れに...

### 余談
ここ最近の gamecontroller.js を使った記事では、純正の DualShock 4 を使っていますが、無線機能を搭載してない有線のみで使える安価な DualShock 4 っぽいコントローラーを見かけて気になっています。

具体的には、大垣で行われたモノ作り系の展示イベント（メーカーフェア）に、一緒のブースで出展した @kenichih さんが展示に使っていて、そして以下の記事にリンクを書かれているものです。

●Ogaki Mini Maker Faire 2022出展記 (GUNPLA Shooting 展示編) - Qiita
　https://qiita.com/kenichih/items/6ec9b8114c94dfc4baed

これも試してみたい！、と思ってポチりました 笑