走らないと進めないマリオカートを作ってみた【家で過ごそう】【運動不足解消】

この記事を書いている2020年4月現在、新型コロナウイルスによる外出自粛が続いています。
どうしても運動不足になりがち、気分も塞ぎがち…ということでNintendo Switchのコントローラーをハックして「走らないと進めないマリオカート」を作ってみました。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">新作マリオカートのプロトタイプ（？）<br><br>新しいマリオカートはコロナの影響から、自宅で運動不足を解消できるように、実際に走らないと進めないようです。笑<a href="https://t.co/TE4dp2QwQG">https://t.co/TE4dp2QwQG</a><a href="https://twitter.com/hashtag/%E3%82%A8%E3%82%A4%E3%83%97%E3%83%AA%E3%83%AB%E3%83%95%E3%83%BC%E3%83%AB?src=hash&amp;ref_src=twsrc%5Etfw">#エイプリルフール</a> <a href="https://twitter.com/hashtag/%E6%96%B0%E5%9E%8B%E3%82%B3%E3%83%AD%E3%83%8A%E3%82%A6%E3%82%A4%E3%83%AB%E3%82%B9?src=hash&amp;ref_src=twsrc%5Etfw">#新型コロナウイルス</a> <a href="https://twitter.com/hashtag/%E9%81%8B%E5%8B%95%E4%B8%8D%E8%B6%B3%E8%A7%A3%E6%B6%88?src=hash&amp;ref_src=twsrc%5Etfw">#運動不足解消</a> <a href="https://twitter.com/hashtag/nintendoswitch?src=hash&amp;ref_src=twsrc%5Etfw">#nintendoswitch</a></p>&mdash; Ginger (@ginger_you) <a href="https://twitter.com/ginger_you/status/1245303592283586560?ref_src=twsrc%5Etfw">April 1, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

↑プロトタイプによるプレイ動画です。実際にやってみると想像以上にいい運動になりました。マリオカート自体がすごく楽しいので、楽しく運動ができるのが良いなと思いました。

#概要
###これを作ったきっかけ
手軽な電子工作で人気のArduinoですが、実は一部のArduinoはSwitchのコントローラーとして使うことが出来ます。
マリオカートのAボタン（アクセル）を加速度センサーに対応させれば、自分が走ることで前に進むマリオカートが作れます。
家で楽しく過ごす方法が求められている今、これは運動不足も解消できて良いのでは！？と思い作ってみることにしました。

###今回作るもの
今回はブレッドボード上で配線するだけで作れるバージョンをご紹介します。
こちらは少しボタン数が少ないのですがとりあえず遊ぶ分には問題ありません。
![_IMG2629-2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/164437/ccfcc8b5-edae-9a05-2200-101da00c72c1.jpeg)

次に、プリント基板や3Dプリントを発注する必要がありますが、クオリティを上げたものをご紹介します。
こちらについては、<a href="https://qiita.com/ginger/items/3ae4e65eb2aa7c9749e4">次の記事</a>で作り方を解説していきます。
プリント基板や3Dプリントというとややハードルが高い感じもありますが、基板や3Dプリント用のデータはDLできるようにしてありますし、発注の仕方も解説してますので手順通りにやっていただければ割と簡単に制作できると思います。
![_IMG2767.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/164437/2c332bc2-376d-aeab-6396-5b47707319f2.jpeg)

###ご注意
「Nintendo Switch利用規約」における第1条第5項「任天堂の許諾を受けていない本ゲーム機の周辺機器およびソフトウェア等」の使用にあたる可能性がありますので、利用は自己責任でお願いします。

#作り方
##必要なもの
<a href="https://www.switch-science.com/catalog/1623/">Arduino Pro Micro</a>：¥2538　×1
<a href="http://akizukidenshi.com/catalog/g/gP-03648/">タクトスイッチ（小）</a>：¥10　×6個
<a href="http://akizukidenshi.com/catalog/g/gP-09827/">タクトスイッチ（大）</a>：¥30　×2個
<a href="http://akizukidenshi.com/catalog/g/gM-05153/">加速度センサ</a>：¥850　×1
<a href="http://akizukidenshi.com/catalog/g/gI-11639/">LED</a>：¥20　×1
<a href="http://akizukidenshi.com/catalog/g/gP-00315/">ブレッドボード（中）</a>：¥270 ×1
<a href="http://akizukidenshi.com/catalog/g/gP-05155/">ブレッドボード（小）</a>：¥130 ×1
<a href="http://akizukidenshi.com/catalog/g/gC-05371">ジャンパーワイヤー（オス-オス）</a>：¥180　×1パック（18本入）
<a href="https://www.amazon.co.jp/gp/product/B071S5NTDR/ref=ppx_yo_dt_b_asin_title_o03_s00?ie=UTF8&psc=1">USBケーブル3m（Aオス-microBオス）</a>：¥698　×1

※Arduino Pro Microは<a href="https://www.switch-science.com/catalog/3914/">こちらのSwitch Science版</a>でも同じように使えると思います（少し安いです）
※マイコンはPro Microでなくても、「ATmega 32U4」というチップを採用しているものであれば使うことが出来ますが、その場合プログラムの修正が必要になります。
※タクトスイッチは上記のものでなくてもOKで、お好きなスイッチを使ってください。
※加速度センサーも上記のものでなくてもOKですが、違うものを使う場合、プログラムの修正が必要になります。
※USBケーブルは長いもののほうがプレイしやすいと思います。

##回路
![200425-01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/164437/99dae9e4-30f3-71a4-f29a-f1d318204338.png)
少々配線量が多いのですが、実は単純な配線になっていて、各タクトスイッチは片方の端子をGNDに接続してください。その上で、もう一方の端子は以下の通りに配線してください。

- Lボタン：2番
- Rボタン：3番
- Aボタン：4番
- Bボタン：5番
- 十字キー上：6番
- 十字キー右：7番
- 十字キー下：8番
- 十字キー左：9番

また、加速度センサーは以下のように配線してください

- 1番ピン：VCC
- 2番ピン：VCC
- 3番ピン：GND
- 4番ピン：何にもつなぎません
- 5番ピン：GND
- 6番ピン：A0
- 7番ピン：A1
- 8番ピン：A2

##プログラムと書き込みの注意点
ここまで配線ができたらあとはマイコンにプログラムを書き込めば完成なのですが、その前に少し下準備が必要になります。

###IDEのインストール
<a href="https://www.arduino.cc/en/Main/Software">こちら</a>からArduinoのIDEをダウンロードしてください。
※Macをお使いの方でOSが最新のCatalinaだと書き込み時にエラーが出ることがあります。その場合「HOURLY BUILDS」の方をDLしてみてください。

###ライブラリのインストール
Switchにコマンドを送るために、Arduinoのライブラリを2つインストールしておく必要があります。
こちらから最新のものをダウンロードし、解凍したものをArduinoのLibrariesフォルダに入れてください。
https://www.arduinolibraries.info/libraries/arduino-stl

また、こちらのライブラリも同様にDLして同じフォルダに入れておきます。
https://github.com/interimadd/NintendoSwitchControll
![200425-03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/164437/77814631-e5a4-7737-d01d-fa9f108fd56b.png)

###boards.txtの書き換え
boards.txtというファイルの一部を書き換えます。

- Windowsの方：Program files(x86)>Arduino>hardware>arduino>avr
- Macの方：/Users/ユーザー名/Library/Arduino15/packages/arduino/hardware/avr/1.8.2

変更内容は

285行目　leonardo.vid.1=0x0f0d
286行目　leonardo.pid.1=0x0092
311行目　leonardo.build.vid=0×0f0d
312行目　leonardo.build.pid=0×0092

※boards.txtの場所は環境によって違う可能性があります。
※boards.txtは念の為バックアップを取って書き換えてみてください。
※詳しくはこちらのサイトを参照させていただきました。
https://note.com/itogt/n/n6119cc78d2de

###プログラムの書き込み
ここまで準備ができましたら以下のプログラムを書き込みます。
その際、ボードは「Arduino Leonardo」を選んでください。
![スクリーンショット 2020-04-26 1.28.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/164437/2f291b57-e69b-998f-c7e9-cf3e09724fa0.png)

```c:qiita.rb
#include <SwitchControlLibrary.h>

int lButton=2;
int rButton=3;
int aButton=4;
int bButton=5;
int up=6;
int right=7;
int down=8;
int left=9;
int LED=16;
bool keyPress=false;
int moveCount=0;
int r;
int x;
int y;
int z;
int preR=0;
int threshold=1000;

//このlevelという数字を上げていくと、たくさん動かないとAボタンが押されなくなります。
//150くらいにするとハードモード、50くらいだと楽ちんになります。
int level=100;

void setup() {
  // put your setup code here, to run once:
  pinMode(lButton, INPUT_PULLUP);
  pinMode(rButton, INPUT_PULLUP);
  pinMode(aButton, INPUT_PULLUP);
  pinMode(bButton, INPUT_PULLUP);
  pinMode(up, INPUT_PULLUP);
  pinMode(right, INPUT_PULLUP);
  pinMode(down, INPUT_PULLUP);
  pinMode(left, INPUT_PULLUP);
  pinMode(LED, OUTPUT);
  Serial.begin(9600);
}

void loop() {
  
  //////////////////KEY-CONFIG///////////////////

  if(digitalRead(lButton)==LOW){
    Serial.println("lButton");
    SwitchControlLibrary().PressButtonL();
  }else{
    SwitchControlLibrary().ReleaseButtonL();
  }
  if(digitalRead(rButton)==LOW){
    Serial.println("rButton");
    SwitchControlLibrary().PressButtonR();
  }else{
    SwitchControlLibrary().ReleaseButtonR();
  }
  if(digitalRead(aButton)==LOW){
    Serial.println("aButton");
    SwitchControlLibrary().PressButtonA();
  }else{
    //SwitchControlLibrary().ReleaseButtonA();
  }
  if(digitalRead(bButton)==LOW){
    Serial.println("bButton");
    SwitchControlLibrary().PressButtonB();
  }else{
    SwitchControlLibrary().ReleaseButtonB();
  }

  keyPress=false;
  
  if(digitalRead(up)==LOW){
    Serial.println("up");
    SwitchControlLibrary().MoveHat(0);
    keyPress=true;
  }
  
  if(digitalRead(right)==LOW){
    Serial.println("right");
    SwitchControlLibrary().MoveHat(2);
    keyPress=true;
  }
  
  if(digitalRead(down)==LOW){
    Serial.println("down");
    SwitchControlLibrary().MoveHat(4);
    keyPress=true;
  }
  
  if(digitalRead(left)==LOW){
    Serial.println("left");
    SwitchControlLibrary().MoveHat(6);
    keyPress=true;
  }
  
  if(keyPress==false){
    SwitchControlLibrary().MoveHat(8);
  }

  //////////////////END-OF-KEY-CONFIG///////////////////

  x=analogRead(A0);
  y=analogRead(A1);
  z=analogRead(A2);

  r=sqrt(pow(x-500,2)+pow(y-500,2)+pow(z-500,2));

  if(moveCount>level){
    moveCount-=level;
  }
  if(moveCount<threshold*3){
    moveCount+=abs(preR-r);
  }

  if(moveCount>threshold){
    SwitchControlLibrary().PressButtonA();
    digitalWrite(LED,HIGH);
    }
  else{
    SwitchControlLibrary().ReleaseButtonA();
    digitalWrite(LED,LOW);
  }

  preR=r;
  delay(16);
  
}
```

#完成
いかがでしたでしょうか！？マリオカート以外にも色々なゲームに応用できそうな気もします。

###クオリティアップ版を作りたい方へ
プリント基板と3Dプリントを使えばもう少ししっかりしたコントローラーに仕上げることも出来ます。
こちらについては<a href="https://qiita.com/ginger/items/3ae4e65eb2aa7c9749e4">次の記事</a>にて詳しく作り方を解説していきます。
![_IMG2756.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/164437/660b556c-c567-3d75-3f09-123662031f3d.jpeg)