toio のビジュアルプログラミングで 2台のキューブを使ってみた

## はじめに

先日、[toio のビジュアルプログラミング](https://toio.io/programming/visual-programming.html)が更新されました。この更新で、念願の [Windows 10 対応](https://note.toio.io/n/nce33be04b2eb?magazine_key=m63c44c67c36d) に加えて、「開発者版」限定ではありますが、2台のキューブを同時に動かすことができるようになりました。
そこでこの記事では、キューブ 2台を使った作例に加え、覚えておくと便利なプログラムのパターンを紹介したいと思います。
![IMG_1175.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141406/5784e131-8348-40bb-9c1b-3c80ae426196.jpeg)
2台のキューブを動かすまでの手順は、[toio 公式の note 記事](https://note.toio.io/n/nb6281d260431) が詳しいので、そちらを参照してください。

ちなみに、ここ紹介する作例は Surface Go と MacBook Pro で動作することを確認しています。


## 2台のキューブを順番に動かす

まずは簡単な例として、「1台目のキューブが前進した後、2台目のキューブが前進する」というプログラムを作ってみます。
![00626.2019-12-24 16_04_28.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141406/288ea3c9-fe25-8920-9586-5aea0d705b29.gif)
2台のキューブを順番に動かす場合は、キューブを動かすブロックの後に、もう一方のキューブを動かすブロックをつなげるだけです。
![スクリーンショット 2019-12-23 23.47.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141406/e27838e9-6b24-a52e-36a8-baedff481d94.png)


## 2台のキューブを同時に動かす

今度は 2台のキューブを同時に動かします。
![00627.2019-12-24 16_03_24.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141406/d3f9b691-77c6-8d92-8504-20e2bf3f72ad.gif)
2台のキューブを同時に動かす場合、プログラムの仕方はいくつかあります。
シンプルに実現するには、キューブを動かすブロックと、もう一方のキューブを動かすブロックを (つなげずに) 離して配置し、それぞれのブロック実行のトリガーとして「旗が押されたとき」といったイベントブロックを使います。
![スクリーンショット 2019-12-23 23.49.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141406/1be7d6b6-4392-2596-413d-f899ed32f456.png)
このようにブロックを配置することで、旗を押したときに 2つのブロック群が同時並行で実行を開始し、2台のキューブを同時に動かすことができます。
いわゆる「マルチスレッド・プログラミング」を簡単に実現できるところが、このビジュアルプログラミングの長所のひとつです。

このように、「イベントをトリガーに同時並行で実行する」というパターンは様々な用途で便利に使えますので、覚えておくと良いでしょう。


## 追いかけっこ

続いて、「1台目のキューブが 2台目のキューブを追いかけ続ける」という追いかけっこのプログラムを作ってみます。
![00632.2019-12-24 16_01_27.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141406/7596168f-d892-d923-e526-87f09d6e983b.gif)
このプログラムは非常にシンプルで、x座標と y座標を指定して 1台目のキューブを動かすブロックの「x座標」と「y座標」に、2台目のキューブの x座標と y座標をあてはめます。
これを「ずっと」の無限ループを使って繰り返し実行することで、延々と追いかけ続けるプログラムになります。
![スクリーンショット 2019-12-24 0.32.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141406/df7e4061-355f-ee47-a8ef-02efc4879c99.png)


## もう一方のキューブの方を向く

次に、「1台目のキューブが 2台目のキューブの方を向き続ける」というプログラムを作ってみます。
![00634.2019-12-24 16_07_04.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141406/164d27ae-505f-105a-c6b2-a43ed42648df.gif)
このプログラムは若干複雑です。特に三角関数が苦手な方にとっては難解な数式を使っていますので、すべてを理解する必要はないと割り切って、「この動きを実現したいときは、このようにブロックを並べればいいんだ」と捉えて、利用の際はこのまま使い回すのが良いかと思います。
![スクリーンショット 2019-12-24 0.41.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141406/05cd5715-8258-6c00-0eeb-a29b0ca0ede5.png)

まず、1台目のキューブの位置を原点としたときの、2台目のキューブへ向かうベクトルを考えます。
![ScratchVector.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141406/591def33-d881-50a7-2c96-6a1dd7ff50b8.png)
このベクトルの x座標と y座標を求めます。
![ScratchAtanVector.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141406/4739d696-5355-36c3-4176-5d6f9f4b1893.png)
このビジュアルプログラミングの座標系では、y軸に向かう方向が 0度で、時計と同じ向きに回ることで角度が増えます。よって、y軸に対するベクトルの角度が、今回の「求めたい角度」となります。
![ScratchAtanAngle.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141406/7850dc5c-5841-844a-35d4-afff8edd5fa2.png)
この角度を求めるために関数 atan (アークタンジェント) のブロックを用います。
![スクリーンショット 2019-12-24 11.59.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141406/32d813b1-fe22-d7d0-df51-e68cc817eab9.png)

ただ、今回は 360度の範囲で角度を求めたい一方で、この関数 atan は -90度から 90度の範囲でしか角度を得られないため、不足する 180度の範囲を補う必要があります。
![ScratchAtan2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141406/15ff7e11-5b00-9aed-ca10-0401d1f2942b.png)

それが式の後半で、1台目のキューブから 2台目のキューブへ向かうベクトルの y軸が負だったとき、すなわち 2台目のキューブの y座標が 1台目のキューブの y座標より小さいとき、atan で求めた角度に 180度を足しています。
![スクリーンショット 2019-12-24 1.07.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141406/df06c956-739c-049d-f869-894a0a201f89.png)
ここでは、一見特殊な (けど、一般的なプログラマーには比較的よく知られた) パターンを利用しています。

このビジュアルプログラミングでは、真偽ブロックは基本的に true か false を返しますが、これを値として数式の中で用いると true は 1 に、false は 0 として扱われます。
たとえば、
![スクリーンショット 2019-12-24 1.01.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141406/bd8d35d1-95b4-c0da-83cb-64978645c53b.png)
は、0 は 50 より大きいのでこの真偽ブロックは false となりますが、これに 1 をかける数式の中で用いると
![スクリーンショット 2019-12-24 1.02.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141406/b7fdb1cb-6acc-72f8-adcc-af04cd3a729c.png)
となり、「0 > 50」は 0 として扱われることがわかります。

一方、
![スクリーンショット 2019-12-24 1.04.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141406/4d986cd1-8ffa-8605-2224-b97e8b496926.png)
の場合は、
![スクリーンショット 2019-12-24 1.05.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141406/b1a61283-b0df-de91-587e-5a0e2d58715b.png)
となり、「100 > 50」は 0 として扱われます。

これを活用することで、本来であれば
![スクリーンショット 2019-12-24 1.11.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141406/da745b4c-c947-a31c-0bd9-3432be626563.png)
のように、縦方向に伸びる条件分岐のブロックを使うところを、横並びの数式の中で同等の処理を実現することができます。

このようにして求めた角度を変数「相手の向き」に入れて、1台目のキューブの向きを変えるブロックにあてはめると、1台目のキューブが 2台目のキューブの方を向く動きを実現することができます。
![スクリーンショット 2019-12-24 12.54.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141406/c55440cc-6fac-634d-f379-988e637f228c.png)


## いろいろな音を鳴らす

これまで見てきた作例とは趣向を変えて、ここでは 2台のキューブを入力デバイスとして利用して、両手に持ったキューブでマットに触れることでいろいろな音を鳴らすことができるプログラムを作ってみたいと思います。

まず、1台目のキューブがマットに触れる位置に応じて、鳴らす音の種類を変えることができるようにします。

音を鳴らすために、ここでは「終わるまで ○ の音を鳴らす」のブロックを使っています。このブロックは通常、リスト表示される音の一覧から手動で鳴らす音を選択します。
![スクリーンショット 2019-12-24 13.15.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141406/01042fd8-87b6-a3fc-f089-fb476ddeb695.png)
実はこの ○ の箇所は値をあてはめることができ、その値に応じて鳴らす音を変えることができます。
![PlaySoundWithValue.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141406/edf00306-7896-75fd-d449-38d838e9feae.gif)
値と鳴らす音の関係性については、「音」のタブを見るとわかるように、それぞれの音の左上に 1 や 2 などの通し番号がついていて、値が 1 のときは 1つ目の音が、2 のときは 2つ目の音が鳴るようになっています。
![スクリーンショット 2019-12-24 13.22.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141406/a6f5c8a4-9f30-a392-b9f3-d23030695d8f.png)
ここでは、キューブがマットに触れたときの横方向の位置 (列) に従って、鳴らす音を変えてみましょう。値としてキューブの「マスの列番号」を用いますが、マスの列番号の範囲は -4 から 4 までのため、これに 5 を足して 1 から 9 にしています。
![スクリーンショット 2019-12-24 13.36.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141406/3de9cabc-92b7-1b16-20cd-6f71ebc90a3b.png)
キューブがマットに触れている間は音を鳴らし続け、マットから離したときに音を止めるよう、ブロックを以下のようにと並べます。
![スクリーンショット 2019-12-24 13.54.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141406/7a1e1be1-7836-e2b4-2110-eeb3c963ca46.png)

ここで出てきた「マットに触れたとき 〜 マットに触れた ではない まで繰り返す」というブロックの並びは、「キューブがマットに触れているときはずっと繰り返し、マットから離れたときに終了」という処理を実現します。一見複雑ですが、いろいろなケースで便利に使えますので覚えておくと良いでしょう。

ここまでのプログラムで、キューブを横方向に動かすことによって鳴らす音の種類を変えることができるようになりました。縦方向の動きがまだ残っていますので、これで音のピッチを変えられるようにします。
![スクリーンショット 2019-12-24 13.56.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141406/8123bd06-6ad8-2997-bd8a-cc25ffbeb045.png)

上述の「2台のキューブを同時に動かす」で紹介したように、イベントブロックをトリガーとして 2つの処理を同時並行で実行しています。上半分が上で説明した「横方向で鳴らす音の種類を変える」処理、下半分が新たに加えた「縦方向で鳴らす音のピッチを変える」処理です。

さらに 2台目のキューブを使って、鳴らす音の左右位置や音量を変えられるようにします。
![スクリーンショット 2019-12-24 14.02.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141406/1eb32260-bdc2-cea2-71f4-fbeca584bbdf.png)
ブロック「左右にパン」の値は -100 から 100 まで、「音量」の値は 0 から 100 までですので、キューブの列番号や行番号を補正してから代入しています。

## たくさんの星を描く

最後に、2台のキューブを使ってたくさんの星を描くプログラムを作ってみます。![00640.2019-12-24 16_39_58.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141406/7e57bf7b-3811-2f38-2649-aaf32b4347ca.gif)
キューブが星の軌跡に従って動くには、「キューブを前に一定距離動かした後、144度回す」という動きを 5回繰り返します。
![スクリーンショット 2019-12-24 14.08.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141406/f7ffd9e6-225d-7018-83e2-79c1e7db29ef.png)
繰り返しの回数「5」と回す角度の「144」を、たとえば 4 と 90 に変えると正方形になるなど、他の値に変えることで様々な形を描くことができます。そこで、(今回は使いませんが、今後の機能追加のためにも) それぞれ「回数」「角度」という変数に置き換えます。
![スクリーンショット 2019-12-24 14.10.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141406/d578f55f-c5f2-9f4f-3278-be501cbc33a1.png)

次に、このキューブの軌跡を PC の画面に線として描けるようにします。
線を描くには拡張機能の「ペン」を利用します。
![スクリーンショット 2019-12-24 14.21.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141406/29a0fc40-ae95-0a04-a967-4f00744189b5.png)
ペンで描く位置はスプライトの位置に紐づくため、まずはスプライトがキューブの位置に連動して動くようにプログラムを作ります。
![スクリーンショット 2019-12-24 14.23.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141406/3fffc7a7-fdb2-3760-1398-aef94bcc8a9b.png)
ここではスプライトの位置だけでなく、向きもキューブと連動するようにしています。

ペンで実際に線を描き始めるには、拡張機能「ペン」のブロック「ペンを下ろす」を使います。
![スクリーンショット 2019-12-24 14.25.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141406/68b1f8d9-2b7c-b698-8b7e-d597c0f74b53.png)

この処理を繰り返すたびに異なる位置に星を描けるよう、ランダムな位置にキューブを動かす処理を追加します。
![スクリーンショット 2019-12-24 14.27.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141406/3ab82ea3-ba17-9c9e-a227-c78400eea98d.png)
このとき、ランダムな位置にキューブを動かす際は線を描きたくないので、ブロック「ペンを上げる」を使っています。

2台目のキューブも同様に、まずランダムな位置へ移動してから、星を描くようにプログラムを作ります。このとき、1台目のキューブとは独立の線として描くため、スプライトを新たに 1つ追加して、そのスプライトにおけるプログラムとして 2台目のキューブの動きを作ります。

ただ厄介なことに、1台目のキューブ用に作ったプログラムを 2台目のキューブで再利用することはできません。これは、キューブのブロックは「1台目用」「2台目用」がそれぞれ個別に提供されていて、「1台目」か「2台目用」かを動的に切り替えることがでないためです。
加えて、このビジュアルプログラミング環境では、スプライトをまたがってブロック群をコピー＆ペーストすることができません。1台目のキューブと 2台目のキューブで同じ処理を実行したい場合、1台目用にブロックを並べた後、2台目用のブロックも同様にゼロから並べ直す必要があります。

最後のステップとして、これまで見てきたキューブ 2台 (スプライト 2つ) の処理を、旗を押すことで同時に開始できるようにしましょう。「旗が押されたとき」をトリガーに、「星を描く」というメッセージを送るようにします。キューブ 2台が星を描く処理の冒頭でそのメッセージを受け取り、処理開始のトリガーとします。

下図は、1台目のキューブのプログラムです。
![スクリーンショット 2019-12-24 14.38.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141406/e825872c-f95a-115f-29fb-36db36f945cc.png)
下図は、2台目のキューブのプログラムです。
![スクリーンショット 2019-12-24 14.41.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141406/bcb73aae-d9e8-5d1b-4b8d-35c60d56768a.png)

## まとめ

キューブ 2台を使った作例と、いくつかのプログラムのパターンを紹介しました。キューブ 1台だけを使う場合と比べて、楽しみ方の可能性が大きく広がったように感じます。
皆さんもぜひ、ここで紹介した作例やパターンを参考に、いろいろな遊びや道具を考えて作ってみてください。

$$\style{background-color:pink;padding:32px} {\huge{　メリークリスマス!　}}$$