ウルトラソウルﾊｲﾊｲﾊｲﾊｲﾊｲﾊｲﾊｲﾊｱｱｱｲｯｯｯゲーム作った

#ウルトラソウルでもっとﾊｱｱｱｱｲｨｯｯｯｯｯｯしたい！
「そして輝く？」と言われたら皆さんはなんと答えますか？
そうですね、「__ｳﾙﾄﾗｿｳｳｩｯｯｯｯｯ　ﾊｱｲｨｯｯ__」ですよね。

でもその__ﾊｱｱｱｱｲｨｯｯｯｯｯｯ1回で足りてますか？？？__
「私、__もっとﾊｱｱｱｱｲｨｯｯｯｯｯｯしたい。。。一回じゃ足らない！！__」と悩んでいる方もいらっしゃるのではないでしょうか。
そこで今回はYoutube Player APIを利用して__たくさんﾊｱｱｱｱｲｨｯｯｯｯｯｯできる__ゲームを作ってみました。
ただﾊｱｱｱｱｲｨｯｯｯｯｯｯしても面白くないので、音ゲー要素をちょっと入れてみてます。
コードも是非是非ご覧ください！

Appは[ここから](https://haihaihaihaihaihaihaihaaai.ml/)
コードは[ここから](https://gist.github.com/canonno/e62f67c6fe77cafb8224b66edf4d568d)
[前回の記事](https://qiita.com/canonno/items/964b9ff613ced1b217c2)も是非ご覧くださいね。


#完成デモ
##しっかりﾊｱｱｱｱｲｨｯｯｯｯｯｯ
「結末ばかりに気を取られ」をクリックすると、__複数音源から「ウルトラソウル」が一斉に再生されます。__
__それぞれの音をしっかり聞き分け、「ﾊｱｱｱｱｲｨｯｯｯｯｯｯ」のタイミングでﾊｱｱｱｱｲｨｯｯｯｯｯｯボタンをクリックする__というゲームです。
冒頭に「いくつのｿｳﾙでﾊｱｱｱｱｲｨｯしますか」と聞かれるので、そこで選んだ数だけ音源が重なります。
最大8つの音源の聞き分けがクリアできたらﾊｱｱｱｱｲｨﾏｽﾀｰです。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">ウルトラソウルﾊｱｱｱｱｲｨｯのﾊｱｱｱｱｲｨｯでﾊｱｱｱｱｲｨｯできる音ゲー作りました。何重にも重なる音源からﾊｱｱｱｱｲｨｯを聞き分けてボタンをクリックしてください！<a href="https://twitter.com/hashtag/protoout?src=hash&amp;ref_src=twsrc%5Etfw">#protoout</a> <a href="https://t.co/DEBAoCQPIA">pic.twitter.com/DEBAoCQPIA</a></p>&mdash; canonno @クラファンご支援ありがとうございました！ (@canonno_blog) <a href="https://twitter.com/canonno_blog/status/1342123576716009473?ref_src=twsrc%5Etfw">December 24, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>




##ﾊｱｱｱｱｲｨｯｯｯｯｯｯ判定
調査の結果、今回利用した音源で__「ﾊｱｱｱｱｲｨｯｯｯｯｯｯ」の「ﾊ」の「h」のタイミングは67.016秒地点__ということが分かりました。
これと「ﾊｱｱｱｱｲｨｯｯｯｯｯｯ」を押したタイミングの差に応じて「早すぎる」だとか「遅い」だとか言われます。
例えば5つの音源が再生されている場合、5つの「ﾊｱｱｱｱｲｨｯｯｯｯｯｯ」全てを一定範囲内のタイミングでクリックする必要があるイメージです。
全ﾊｱｱｱｱｲｨｯのクリック結果を総合した結果が最初に出ますので、是非是非パーフェクト目指して頑張ってみてください。

<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/666990/c7717649-989d-20de-a43b-5ce447791d57.png">


#実装こまごま
##p5jsまわりYoutube Player APIまわり
これまでの記事でもずっと扱ってきているので、p5jsまわりは[こちらの記事](https://qiita.com/canonno/items/00738c7d928c3ec655d5)を、Youtube Player APIまわりは[こちらの記事](https://qiita.com/canonno/items/8b0be6309b479ec5cdcc)をご覧ください。
今流行りの湯婆婆関連ゲームも作ったので[こちらの記事](https://qiita.com/canonno/items/fb3b2f10937d0ba80cb4)も是非是非ご覧になってくださいね。

##複数音源の再生
今回複数のウルトラソウルを同時に流しています。
当初は、例えば音源を3つ再生するときは、1つめのイントロが流れた数秒後に2つめのイントロ、というように開始時間のラグを作る実装を考えていました。
僕の知識の範囲ではsetTimeoutをfor文の中に入れ込めばいいのかなーと思って実装するも、うまく実装ができず。

調べた結果、どうもsetTimeoutを使うのは筋が悪そうな様。
今回はあきらめましたが、次回以降の備忘録としてメモメモ。
・[javascriptのsetTimeoutが即実行されてハマった](https://qiita.com/sirojake/items/26618081bbb33e918aa4)
　そもそもsetTimeoutの文法をちゃんと理解してなかった・・・なるほど
・[JavaScriptでループ毎に一定時間待つ方法](http://blog.kabadna.com/20110719-1282/)
　自分自身を何度も呼び出すという実装。

で結局、ランダムで開始位置を決めて再生する、という手にしました。
その部分がこちら。

```js
    //読み込んだ際に最初に走る処理
      function onYouTubeIframeAPIReady() {
        //playerの定義
        player1 = new YT.Player('player1', cond_dic);
        player2 = new YT.Player('player2', cond_dic);
        player3 = new YT.Player('player3', cond_dic);
        player4 = new YT.Player('player4', cond_dic);
        player5 = new YT.Player('player5', cond_dic);
        player6 = new YT.Player('player6', cond_dic);
        player7 = new YT.Player('player7', cond_dic);
        player8 = new YT.Player('player8', cond_dic);

        player_list= [
        {"player":player1,"sec":sec1},
        {"player":player2,"sec":sec2},
        {"player":player3,"sec":sec3},
        {"player":player4,"sec":sec4},
        {"player":player5,"sec":sec5},
        {"player":player6,"sec":sec6},
        {"player":player7,"sec":sec7},
        {"player":player8,"sec":sec8},
      ]}

      //結末ばかりに気を取られをクリックするとここが実行される
      function startSound(){
        //最初のダイアログに入れた値がstageに入り、その回数だけforが回る
        for (let idx= 0;idx<stage;idx++){
          //forの回数だけplayerにloadVideo&playVideoされる
          player_list[idx]["player"].loadVideoById({
          videoId:"Ujb-ZeX7Mo8",
          startSeconds:player_list[idx]["sec"],
          endSeconds:80,
        })
          player_list[idx]["player"].playVideo();
        }
      }
```
開始時間はランダム性をいれたかったのでこんな感じ。
secは音源間の間隔調整のためのパラメータ、baseは全体の開始時間を調整するためのパラメータです。
こう書くことで、最低限sec1<sec2<sec3<・・・sec8となるように実装できます。
こうすれば、player1が一番最初にスタートし、順にplayer2,player3・・・と続くようにできるので、判定処理が簡単にかけるようになるなぁなどと期待していました。

```js
      const sec = 1.5
      const base = 35
      let sec1 = base
      let sec2 = base + Math.random() * sec
      let sec3= base + sec + Math.random() * sec
      let sec4 = base + sec*2 + Math.random() * sec
      let sec5 = base + sec*3 + Math.random() * sec
      let sec6 = base + sec*4 + Math.random() * sec
      let sec7 = base + sec*5 + Math.random() * sec
      let sec8 = base + sec*6 + Math.random() * sec
```

##ﾊｱｱｱｱｲｨｯ判定処理
これがちょっと面倒だった部分。
先ほどsec1<sec2<sec3・・・とすることによって、player1が一番最初にスタートし、順にplayer2,player3・・・と続くようにしました。
ところが実際やってみると、__読み込み待ち時間がそれぞれのプレイヤーで異なるため、時々前後が逆転してしまうことが判明__。
これを調節するため並び替え処理を組み込んで実装しました。

```js
    function stopSound(){
　　　　 //ﾊｱｱｱｱｲｨｯをクリックした瞬間のすべてのplayerの時間を取得
        let player_time_list = []
        for (let idx=0;idx<stage;idx++){
          player_time_list.push(player_list[idx]["player"].getCurrentTime())
        }
        //すべてのplayerの時間を並び替える
        player_time_list.sort(compare)
        
        //count番目の音源とhai_time(正解時刻)との差を取得
        let dif = player_time_list[count]-hai_time;
        loss += Math.abs(dif)
        result = hantei(dif)
        
        label += "\n"+(count+1)+"ﾊｱｨ:"+result
        count++

　　　  //最終結果発表
        if (count == stage){
          result = final_result(loss)
          label += "\n\n結果:"+result
        }

        function compare(a,b){
          return b- a;
        }
      }
```


#さいごに
　最近モノづくりモチベが下がるときがあるので、ちょっとクレイジーな__ウルトラソウルdriven__なネタを考えるようにしています。
　是非皆様もやる気が出ないときはウルトラソウルしてみてはいかがでしょうか！

　最後まで読んでいただきありがとうございました。LGTMしていただけると励みになります！