距離センサを使ってポケモンをゲットしてみた

## ポケモンを3次元でゲットしてみたい
前回の投稿を見ていただいた方はお気づきだろうが今回もポケモンに関する記事だ。前回はクイズに正解をするとポケモンを捕まえられるという仕様になっていたのだが、 **『現実世界でポケモンを捕まえたい！』** という小学生からの夢を実現するために、現実世界でポケモンを捕まえた気分になれるようなプロトタイプを作成した。

https://qiita.com/kosuke0517lab/items/7fbe11c337ea3e8c7d16

## 遊び方
- 『ポケモン』とLINEへ送信すると、捕まえる対象のポケモンの画像がLINEへ送られてくる。
- モンスターボール（？）をポケモンに向けて投げる。
- 『ゲーム』とLINEへ送信をすると、距離センサでモンスターボールとの距離を計測する。
　 　3~5cmの間にモンスターボールが止まればポケモンをゲットできる。
- ポケモンがゲットできた際には『やった～！　○○を捕まえた！』とLINEへ送信。

## どんなプロトタイプ？
まずは下記の動画を見ていただきたい。

<iframe width="560" height="315" src="https://www.youtube.com/embed/9ES0Zlm82uE?start=9" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2618860/b579cbc6-a653-0338-8193-d65d5cdd6db6.png)
①『ポケモン』とLINEへ入力して送信する。
②捕まえる対象のポケモンの画像がLINEへ送られてくる。
③モンスターボール（？）をポケモンに向けて投げる。
④『ゲーム』とLINEへ入力して送信をする。
⑤obnizの距離センサでモンスターボールとの距離を計測する。
⑥測定結果によってメッセージを変える。（ポケモンとの距離が３～５cmのときゲット）
⑦⑥で作成したメッセージをLINEへ送信する。

## 環境
- Node-RED
- JavaScript
- PokeAPI
- LINE Bot
- obniz

## Node-REDのフロー＆obnizの回路
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2618860/793e266f-0222-a9e7-3ff8-4cc4d8ff4139.png)
```
[{"id":"95cb34cf.7a2e48","type":"tab","label":"0420(課題)","disabled":false,"info":""},{"id":"cb1d6d3a.017e1","type":"debug","z":"95cb34cf.7a2e48","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":510,"y":320,"wires":[]},{"id":"11a346f0.5a4c19","type":"obniz-function","z":"95cb34cf.7a2e48","obniz":"9ef07fe3.5d071","name":"","code":"msg.payload = \"finish\";\nawait obniz.wait(1000); \nobniz.close();\n\nreturn msg;","x":340,"y":320,"wires":[["cb1d6d3a.017e1"]]},{"id":"76e43759.3dff68","type":"inject","z":"95cb34cf.7a2e48","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":160,"y":320,"wires":[["11a346f0.5a4c19"]]},{"id":"777fdd48.6543c4","type":"obniz-function","z":"95cb34cf.7a2e48","obniz":"9ef07fe3.5d071","name":"処理を取得","code":"msg.payload = await obnizParts.hcsr04.measureWait();\n\nobniz.display.clear(); // クリア\n\n// 距離を取得\nlet distance = msg.payload;\n// そのままだと小数点以下の桁数がやたら多いので整数に丸めてもよい\ndistance = Math.floor(distance);\n\n// 距離(mm)を格納\nmsg.distance = distance;\n\nreturn msg;","x":790,"y":620,"wires":[["206becc6.2638f4"]]},{"id":"8643bcb3.782","type":"debug","z":"95cb34cf.7a2e48","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1570,"y":600,"wires":[]},{"id":"206becc6.2638f4","type":"switch","z":"95cb34cf.7a2e48","name":"","property":"distance","propertyType":"msg","rules":[{"t":"lt","v":"20","vt":"str"},{"t":"lt","v":"50","vt":"str"},{"t":"lt","v":"100","vt":"str"},{"t":"lt","v":"150","vt":"str"},{"t":"lt","v":"200","vt":"str"},{"t":"gte","v":"200","vt":"str"}],"checkall":"false","repair":false,"outputs":6,"x":970,"y":620,"wires":[["1ae2ee9a.137761"],["3ee8fa40.82e3d6"],["689d12bf.8b551c"],["49951e74.2fbe7"],["7e71ee31.b2c52"],["4d0dfe09.0bb33"]]},{"id":"7e71ee31.b2c52","type":"obniz-function","z":"95cb34cf.7a2e48","obniz":"9ef07fe3.5d071","name":"20cm未満","code":"// 距離が20cm未満のとき\nobniz.display.clear();\nobniz.display.print(msg.distance + ' mm');\n\n//効果音\nfor (let step = 0; step < 3; step++){\n    obnizParts.Speaker.play(200); // 200Hz で音を鳴らす\n    await obniz.wait(300); \n    obnizParts.Speaker.stop(); // 音をとめる\n    await obniz.wait(300); \n}\nobnizParts.Speaker.stop(); // 音をとめる\n\nmsg.payload = (msg.distance + ' mm');\n\nreturn msg;","x":1160,"y":680,"wires":[["e939cc1d.643c5"]]},{"id":"49951e74.2fbe7","type":"obniz-function","z":"95cb34cf.7a2e48","obniz":"9ef07fe3.5d071","name":"15cm未満","code":"// 距離が15cm未満のとき\nobniz.display.clear();\nobniz.display.print(msg.distance + ' mm');\n\n//効果音\nfor (let step = 0; step < 3; step++){\n    obnizParts.Speaker.play(200); // 200Hz で音を鳴らす\n    await obniz.wait(300); \n    obnizParts.Speaker.stop(); // 音をとめる\n    await obniz.wait(300); \n}\nobnizParts.Speaker.stop(); // 音をとめる\n\nmsg.payload = (msg.distance + ' mm');\n\nreturn msg;\n","x":1160,"y":640,"wires":[["79a7a289.4ed26c"]]},{"id":"689d12bf.8b551c","type":"obniz-function","z":"95cb34cf.7a2e48","obniz":"9ef07fe3.5d071","name":"10cm未満","code":"// 距離が10cm未満のとき\nobniz.display.clear();\nobniz.display.print(msg.distance + ' mm');\n\n//効果音\nfor (let step = 0; step < 3; step++){\n    obnizParts.Speaker.play(200); // 200Hz で音を鳴らす\n    await obniz.wait(300); \n    obnizParts.Speaker.stop(); // 音をとめる\n    await obniz.wait(300); \n}\nobnizParts.Speaker.stop(); // 音をとめる\n    \nmsg.payload = (msg.distance + ' mm');\n\nreturn msg;","x":1160,"y":600,"wires":[["e994f1e8.fe969"]]},{"id":"3ee8fa40.82e3d6","type":"obniz-function","z":"95cb34cf.7a2e48","obniz":"9ef07fe3.5d071","name":"5cm未満","code":"// 距離が5cm未満のとき\nobniz.display.clear();\nobniz.display.print(msg.distance + ' mm');\n\n//捕まえた時の効果音\nfor (let step = 0; step < 3; step++){\n    obnizParts.Speaker.play(200); // 200Hz で音を鳴らす\n    await obniz.wait(300); \n    obnizParts.Speaker.stop(); // 音をとめる\n    await obniz.wait(300); \n}\nobnizParts.Speaker.play(1000); // 1000Hz で音を鳴らす\nawait obniz.wait(200); \nobnizParts.Speaker.stop(); // 音をとめる\n\nmsg.payload = (msg.distance + ' mm');\n\nreturn msg;","x":1160,"y":560,"wires":[["49bf9022.4e335"]]},{"id":"1ae2ee9a.137761","type":"obniz-function","z":"95cb34cf.7a2e48","obniz":"9ef07fe3.5d071","name":"３cm未満","code":"// 距離が3cm未満のとき\nobniz.display.clear();\nobniz.display.print(msg.distance + ' mm');\nobnizParts.Speaker.stop(); // 音をとめる\n\nmsg.payload = (msg.distance + ' mm');\n\nreturn msg;","x":1160,"y":520,"wires":[["bf8465dd.08eb88"]]},{"id":"994a68d2.a74da8","type":"ReplyMessage","z":"95cb34cf.7a2e48","name":"","replyMessage":"","x":1600,"y":660,"wires":[]},{"id":"b379c872.4e7ce8","type":"Webhook","z":"95cb34cf.7a2e48","name":"","url":"/webhook","x":100,"y":500,"wires":[["77a2f146.da268"]]},{"id":"a9de1833.378708","type":"function","z":"95cb34cf.7a2e48","name":"メッセージ格納","func":"// msg.payloadにメッセージ本体を入れる\nmsg.input_line = msg.payload;\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":420,"y":500,"wires":[["af452904.7e9ed8"]]},{"id":"1ce6d0f5.4ba6cf","type":"switch","z":"95cb34cf.7a2e48","name":"","property":"input_line","propertyType":"msg","rules":[{"t":"eq","v":"ポケモン","vt":"str"},{"t":"eq","v":"ゲーム","vt":"str"},{"t":"eq","v":"情報","vt":"str"},{"t":"eq","v":"ポッチャマ","vt":"str"},{"t":"else"}],"checkall":"true","repair":false,"outputs":5,"x":570,"y":620,"wires":[["7d8fc672.f1d408"],["777fdd48.6543c4"],["fd6bbdda.8e4c5"],["7a7a8511.33d68c"],["fafe18d6.b2fda8"]]},{"id":"77a2f146.da268","type":"function","z":"95cb34cf.7a2e48","name":"整数生成","func":"//現在の時間を取得\nlet time = new Date();\n\n//月、時、曜日　０始まり\nlet date = time.getDate();\nlet hour = time.getHours();\nlet day = time.getHours();\n\nmsg.id = date + hour * day ;\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":240,"y":500,"wires":[["a9de1833.378708"]]},{"id":"4fde8883.ff7eb8","type":"ReplyMessage","z":"95cb34cf.7a2e48","name":"","replyMessage":"","x":1160,"y":460,"wires":[]},{"id":"88723e94.c4b14","type":"change","z":"95cb34cf.7a2e48","name":"","rules":[{"t":"delete","p":"payload","pt":"msg"},{"t":"set","p":"payload.type","pt":"msg","to":"image","tot":"str"},{"t":"set","p":"payload.previewImageUrl","pt":"msg","to":"poke","tot":"msg"},{"t":"set","p":"payload.originalContentUrl","pt":"msg","to":"poke","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":960,"y":460,"wires":[["4fde8883.ff7eb8"]]},{"id":"7d8fc672.f1d408","type":"function","z":"95cb34cf.7a2e48","name":"画像","func":"// 返信メッセージをhttp requestの結果にする\nmsg.poke = \"https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/other/official-artwork/\"+encodeURI(msg.id)+\".png\"\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":770,"y":460,"wires":[["88723e94.c4b14"]]},{"id":"a88dfcd2.c5039","type":"function","z":"95cb34cf.7a2e48","name":"⑥LINE msg","func":"// 返信メッセージをhttp requestの結果にする\nlet text01 = \"うまくあたらなかった\" ;\nlet text02 = 'あと'+ (msg.distance - 50) + ' mm';\n\nmsg.payload = text01 + \"\\n\\n\" +text02;\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1330,"y":720,"wires":[["8643bcb3.782","994a68d2.a74da8"]]},{"id":"e939cc1d.643c5","type":"function","z":"95cb34cf.7a2e48","name":"⑤LINE msg","func":"// 返信メッセージをhttp requestの結果にする\nlet text01 = \"ざんねん\\n　ポケモンがボールからでてしまった\";\nlet text02 = 'あと'+ (msg.distance - 50) + ' mm';\n\nmsg.payload = text01 + \"\\n\\n\" +text02;\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1330,"y":680,"wires":[["8643bcb3.782","994a68d2.a74da8"]]},{"id":"79a7a289.4ed26c","type":"function","z":"95cb34cf.7a2e48","name":"④LINE msg","func":"// 返信メッセージをhttp requestの結果にする\nlet text01 = \"ああ\\n　つかまえたと思ったのに\";\nlet text02 = 'あと'+ (msg.distance - 50) + ' mm';\n\nmsg.payload = text01 + \"\\n\\n\" +text02;\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1330,"y":640,"wires":[["8643bcb3.782","994a68d2.a74da8"]]},{"id":"e994f1e8.fe969","type":"function","z":"95cb34cf.7a2e48","name":"③LINE msg","func":"// 返信メッセージをhttp requestの結果にする\nlet text01 = \"おしい\\n　あとちょっとのところだったのに\";\nlet text02 = 'あと'+ (msg.distance - 50) + ' mm';\n\nmsg.payload = text01 + \"\\n\\n\" +text02;\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1330,"y":600,"wires":[["8643bcb3.782","994a68d2.a74da8"]]},{"id":"bf8465dd.08eb88","type":"function","z":"95cb34cf.7a2e48","name":"①LINE msg","func":"// 返信メッセージをhttp requestの結果にする\nlet text01 = \"ポケモンが逃げてしまった！\";\n\nmsg.payload = text01;\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1330,"y":520,"wires":[["8643bcb3.782","994a68d2.a74da8"]]},{"id":"4d0dfe09.0bb33","type":"obniz-function","z":"95cb34cf.7a2e48","obniz":"9ef07fe3.5d071","name":"20cm以上","code":"// 距離が20cm以上のとき\nobniz.display.clear();\nobniz.display.print(msg.distance + ' mm');\n\n//効果音\nobnizParts.Speaker.stop(); // 音をとめる\n\nmsg.payload = (msg.distance + ' mm');\n\nreturn msg;","x":1160,"y":720,"wires":[["a88dfcd2.c5039"]]},{"id":"49bf9022.4e335","type":"function","z":"95cb34cf.7a2e48","name":"②LINE msg","func":"// 返信メッセージをhttp requestの結果にする\nlet text01 = \"やった～！\\n\" +msg.ja_name+ \"を捕まえた！\";\n\nmsg.payload = text01;\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1330,"y":560,"wires":[["8643bcb3.782","994a68d2.a74da8"]]},{"id":"fd6bbdda.8e4c5","type":"function","z":"95cb34cf.7a2e48","name":"ポケモンの情報","func":"// 返信メッセージ\nlet text01 = \"名前:\" + msg.en_name +  \"\\n種類:\" + msg.en_genera;\nlet text02 = \"名前:\" + msg.ja_name + \"\\n種類:\" + msg.ja_genera;\nlet text03 = \"重さ:\" + msg.weight +\"kg\"+\"\\n高さ:\" + msg.height +\"m\";\n\nmsg.payload = \"<英語>\\n\"+text01 +\"\\n\\n<日本語>\\n\"+text02+\"\\n\"+text03;\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":800,"y":780,"wires":[["19418edb.a4cf31"]]},{"id":"fafe18d6.b2fda8","type":"function","z":"95cb34cf.7a2e48","name":"凡例","func":"// 返信メッセージをhttp requestの結果にする\nlet text01 = \"『ゲーム』\\n\\tポケモンの捕獲ゲームが始まるよ\\n\";\nlet text02 = \"『ポケモン』\\n\\t捕獲対象のポケモンを表示するよ\\n\";\nlet text03 = \"『情報』\\n\\tポケモンの情報を表示するよ\";\n\nmsg.payload = text01+text02+text03;\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":770,"y":860,"wires":[["19418edb.a4cf31"]]},{"id":"966244a4.fffa28","type":"function","z":"95cb34cf.7a2e48","name":"get_json01","func":"// http requestの結果を取得する\nconst result = msg.payload;\n\n//ポケモンの名前とタイプ\nmsg.en_name = result.name;\nmsg.en_type = result.types[0].type.name;\n\n//体重と高さを変換\nmsg.weight = parseFloat(result.weight)/10;\nmsg.height = parseFloat(result.height)/10;\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":410,"y":560,"wires":[["ac73a07b.2cb3"]]},{"id":"af452904.7e9ed8","type":"http request","z":"95cb34cf.7a2e48","name":"","method":"GET","ret":"obj","paytoqs":"ignore","url":"https://pokeapi.co/api/v2/pokemon/{{{id}}}","tls":"","persist":false,"proxy":"","authType":"","x":250,"y":560,"wires":[["966244a4.fffa28"]]},{"id":"ac73a07b.2cb3","type":"http request","z":"95cb34cf.7a2e48","name":"","method":"GET","ret":"obj","paytoqs":"ignore","url":"https://pokeapi.co/api/v2/pokemon-species/{{{id}}}","tls":"","persist":false,"proxy":"","authType":"","x":250,"y":620,"wires":[["2c98ed40.e06832"]]},{"id":"2c98ed40.e06832","type":"function","z":"95cb34cf.7a2e48","name":"get_json02","func":"// http requestの結果を取得する\nconst result = msg.payload;\n\n//ポケモンの名前\nmsg.ja_name = result.names[0].name;\nmsg.ja_genera = result.genera[0].genus;\nmsg.en_genera = result.genera[7].genus;\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":410,"y":620,"wires":[["1ce6d0f5.4ba6cf"]]},{"id":"19418edb.a4cf31","type":"ReplyMessage","z":"95cb34cf.7a2e48","name":"","replyMessage":"","x":1000,"y":820,"wires":[]},{"id":"c1acd801.2d7138","type":"change","z":"95cb34cf.7a2e48","name":"","rules":[{"t":"delete","p":"payload","pt":"msg"},{"t":"set","p":"payload.type","pt":"msg","to":"image","tot":"str"},{"t":"set","p":"payload.previewImageUrl","pt":"msg","to":"poke","tot":"msg"},{"t":"set","p":"payload.originalContentUrl","pt":"msg","to":"poke","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":960,"y":960,"wires":[["19418edb.a4cf31"]]},{"id":"7a7a8511.33d68c","type":"function","z":"95cb34cf.7a2e48","name":"画像","func":"// 返信メッセージをhttp requestの結果にする\nmsg.poke = \"https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/other/official-artwork/393.png\"\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":770,"y":960,"wires":[["c1acd801.2d7138"]]},{"id":"9ef07fe3.5d071","type":"obniz","obnizId":"0000-0000","deviceType":"obnizboard1y","name":"","accessToken":"","code":"obniz.display.clear(); // 画面を消去\r\n\r\n//obnizParts.servo = obniz.wired(\"ServoMotor\",{ gnd:0, vcc:1, signal:2 });\r\nobnizParts.hcsr04 = obniz.wired(\"HC-SR04\",{ gnd:3, echo:2, trigger:1, vcc:0 });\r\nobnizParts.Speaker = obniz.wired(\"Speaker\",{ signal:10, gnd:11 });"}]
```
![IMG_5053 1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2618860/ab52e115-6c1d-8348-02f6-5564896e0d2d.jpeg)



## Node-REDのフロー解説
### 大まかな流れ
１．クイズのための図鑑NOを生成し、APIからポケモンの情報を取得する。
２．入力したメッセージによって返信を変える。
３．LINEからの入力によって処理を変える。
　３a．LINEからの入力が『ポケモン』のとき
　３b．LINEからの入力が『ゲーム』のとき
　　物体との距離が3cm以上5cm未満のときポケモンを捕まえられる。
　３c．LINEからの入力が『情報』のとき
　３d．LINEからの入力が『ポケモン』のとき



### １．クイズのための図鑑NOを生成し、APIからポケモンの情報を取得する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2618860/8391370a-d1d0-76c8-c972-cb05177b1bdc.png)

今回も前回と同様に1時間毎に変化をする計算方法でIDを生成する。PokeAPIを用いて生成されたIDに対応するポケモンの情報をJSON方式で取得。詳しい計算方法やデータの取得方法については前回の記事を見ていただきたい。

https://pokeapi.co/

https://qiita.com/kosuke0517lab/items/7fbe11c337ea3e8c7d16

### ２．入力したメッセージによって返信を変える。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2618860/fd423a83-bd6d-2b47-cd76-e076d709b644.png)
＜ _switch_ ノード＞の内容
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2618860/b4746d7a-076d-7861-9a8d-9e64cb8eb1da.png)
LINEからのメッセージによって処理を分岐させている。

### ３a．LINEからの入力が『ポケモン』のとき
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2618860/fd564fa9-837a-36de-42cc-949a0a246876.png)

**①画像のURLを変数に格納**
```javascript:画像
// IDに対応するURLを格納する。
msg.poke = "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/other/official-artwork/"+encodeURI(msg.id)+".png"

return msg;
```
変数に手順１で生成したIDに対応するポケモンの画像があるURLを格納する。

**②msg.payloadへLINEに画像を送信するための情報を格納**
＜ _change_ ノード＞の内容
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2618860/604d7cd3-43fa-f26e-d74a-57a5ec9a88d2.png)

③ポケモンの画像をLINEへ送信

### ３b．LINEからの入力が『ゲーム』のとき
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2618860/3faed9a5-9a9c-13b5-17de-02987d59f54d.png)



```javascript:距離を取得
msg.payload = await obnizParts.hcsr04.measureWait();

obniz.display.clear(); // クリア

// 距離を取得
let distance = msg.payload;
// そのままだと小数点以下の桁数がやたら多いので整数に丸めてもよい
distance = Math.floor(distance);

// 距離(mm)を格納
msg.distance = distance;

return msg;
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2618860/b16713b5-8502-57b4-3233-71d1fe81a669.png)

モンスターボールとポケモン(距離センサ)との距離を計測して、距離に応じた処理を行っている。

```javascript:3cm未満
// 距離が3cm未満のとき
obniz.display.clear();
obniz.display.print(msg.distance + ' mm');
obnizParts.Speaker.stop(); // 音をとめる

msg.payload = (msg.distance + ' mm');

return msg;
```

```javascript:①LINE msg
// 返信メッセージ
let text01 = "ポケモンが逃げてしまった！";

msg.payload = text01;

return msg;
```
ポケモン（距離センサ）との距離が近すぎると、ポケモンに逃げられてしまう。

```javascript:5cm未満
// 距離が5cm未満のとき
obniz.display.clear();
obniz.display.print(msg.distance + ' mm');

//捕まえた時の効果音
for (let step = 0; step < 3; step++){
    obnizParts.Speaker.play(200); // 200Hz で音を鳴らす
    await obniz.wait(300); 
    obnizParts.Speaker.stop(); // 音をとめる
    await obniz.wait(300); 
}
obnizParts.Speaker.play(1000); // 1000Hz で音を鳴らす
await obniz.wait(200); 
obnizParts.Speaker.stop(); // 音をとめる

msg.payload = (msg.distance + ' mm');

return msg;
```

```javascript:②LINE msg
// 返信メッセージ
let text01 = "やった～！\n" +msg.ja_name+ "を捕まえた！";

msg.payload = text01;

return msg;
```
ポケモン(距離センサ)との距離が、３～５cmのときにゲットをすることができる。この際、スピーカーで**ポケモンのゲームでの捕獲音を再現している**ところがポイントである。

```javascript:10cm未満,15cm未満,20cm未満
// 距離が10cm未満,15cm未満,20cm未満のとき
obniz.display.clear();
obniz.display.print(msg.distance + ' mm');

//効果音 10cmは3回、15cmは2回、20cmは1回鳴らす
for (let step = 0; step < 3; step++){
    obnizParts.Speaker.play(200); // 200Hz で音を鳴らす
    await obniz.wait(300); 
    obnizParts.Speaker.stop(); // 音をとめる
    await obniz.wait(300); 
}
obnizParts.Speaker.stop(); // 音をとめる
    
msg.payload = (msg.distance + ' mm');

return msg;
```

```javascript:③LINE msg(10cm未満)
// 返信メッセージ
let text01 = "おしい\n　あとちょっとのところだったのに";
let text02 = 'あと'+ (msg.distance - 50) + ' mm';

msg.payload = text01 + "\n\n" +text02;

return msg;
```
```javascript:④LINE msg(15cm未満)
// 返信メッセージ
let text01 = "ああ\n　つかまえたと思ったのに";
let text02 = 'あと'+ (msg.distance - 50) + ' mm';

msg.payload = text01 + "\n\n" +text02;

return msg;
```
```javascript:⑤LINE msg(20cm未満)
// 返信メッセージ
let text01 = "ざんねん\n　ポケモンがボールからでてしまった";
let text02 = 'あと'+ (msg.distance - 50) + ' mm';

msg.payload = text01 + "\n\n" +text02;

return msg;
```
5～20cmの5cm刻みでメッセージ内容と効果音の回数を変えている。

```javascript:20cm以上
// 距離が20cm以上のとき
obniz.display.clear();
obniz.display.print(msg.distance + ' mm');

//効果音は鳴らさない
obnizParts.Speaker.stop(); // 音をとめる

msg.payload = (msg.distance + ' mm');

return msg;
```

```javascript:⑥LINE msg(20cm)
// 返信メッセージ
let text01 = "うまくあたらなかった" ;
let text02 = 'あと'+ (msg.distance - 50) + ' mm';

msg.payload = text01 + "\n\n" +text02;

return msg;
```

20cm以上離れている場合には効果音は鳴らさない。

### ３c．LINEからの入力が『情報』のとき
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2618860/869b1762-5fbe-5849-8881-fb72acd04087.png)
```javascript:ポケモンの情報
// 返信メッセージ
let text01 = "名前:" + msg.en_name +  "\n種類:" + msg.en_genera;
let text02 = "名前:" + msg.ja_name + "\n種類:" + msg.ja_genera;
let text03 = "重さ:" + msg.weight +"kg"+"\n高さ:" + msg.height +"m";

msg.payload = "<英語>\n"+text01 +"\n\n<日本語>\n"+text02+"\n"+text03;

return msg;
```
対象のポケモンの情報をLINEへ送信する。

### ３d．LINEからの入力がa、b、c以外のとき
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2618860/c4d33d3f-4a9a-8c2d-88fc-4ee521327e33.png)
```javascript:凡例
// 返信メッセージをhttp requestの結果にする
let text01 = "『ゲーム』\n\tポケモンの捕獲ゲームが始まるよ\n";
let text02 = "『ポケモン』\n\t捕獲対象のポケモンを表示するよ\n";
let text03 = "『情報』\n\tポケモンの情報を表示するよ";

msg.payload = text01+text02+text03;

return msg;
```
LINEを送信する際の凡例をLINEへ送信する。

## 苦労した点＆頑張った点
・距離センサは物体（モンスターボール）が斜めになっているとうまく反応しないため、常に物体が距離センサに対して正面を迎えるために割りばしでレーンを作成した。
・家に大量にあった段ボールと割りばし、牛乳パックを利用してお金をかけずに作った。
・スピーカーでポケモンのゲームでの捕獲音を再現している。
・Node-REDのフローの可読性をあげるために _switchノード_ を使って条件分岐をわかりやすくした。 

## あとがき
冒頭に載せてあるYouTubeでは一発でポケモンをゲットしているが、実は5,6回捕まえ損ねており、なかなかの難易度があるゲームとなっている。友人にもやってもらい、ゲーム性があって面白いとの評価を貰っているので是非この記事を読んでいる皆さんも遊んでほしい。