祝!スプラトゥーン3発売
いやぁ地震しゃべる君は完成しましたが、記事になかなかかけないまましばらくたってしまいましたw。
さて、9/9に発売されましたね。我が家でも子供二人が叫びながらバトルをしています。細かい部分は変わってはいるようですが、ゲームのルールは前作・前前作を踏襲しているので違和感なく操作できます。まぁS、X帯などの上級者には苦痛になるほどつらいようですが…僕はあんまよくわかりませんw。
イラスト投稿
スプラ3でも2と同じようにイラストを投稿できます。
投稿の仕方がわからん
というかたはイカをどうぞ
街中をいろいろ見ていると
うますぎ!手書きでこれ行ける?
ってのが結構あります。もちろん手書きしている方もいると思いますが、こんなドット絵を描くのには、気の遠くなるような作業が必要となるでしょう。発売されて間もない今、子供たちがバトルで占有しているスイッチで出来るわけありません。ちょっとクグッてみたら、どうやらArduinoで出来るっぽいですね。まぁ色々みつかるんですが
めんどくさいんですよね…WinAVRやらSwitch-Fightstickやら色々入れるのが多すぎる上にターミナル操作があったとりパス通したりとかでやる気がそがれます。そんな難しくないんで、自分で適当に作ろうかなと思いました。
ライブラリは日本人の方が公開されています。ドット打ちとカーソル移動の処理をプログラミングして、画像データを食わせるだけで行けそうです。それでもArduinoIDEの導入、ライブラリの配置程度は必要ですが最小限で行けると思います。
(現在、マイコンさえあれば、書き込み時に必要なArduinoIDE、ライブラリの配置は不要です。下に読み進めてください)
マイコン購入
Arduino Leonardoが必要となります。
マイコンなんて触ったことない!
という人は下の僕の買ったやつを買いましょう。ちょっと触ったことのある人は…
Leonardoじゃなきゃあかんのかい?Nanoあんだけど…
と思う人もいるでしょう。
Leonardoにはシリアル変換器HID機能(接続したときマウス・キーボード・ゲームコントローラーのように振る舞う)がついていますが、Nanoとかだとついていませんので無理です!Leonardoの他にはArduino Micro、Pro Micro(Micro互換機)が使えます。おとなしくLeonardoと書いているものを買いましょう。esp系もシリアル変換器がついてないので無理ですよ
そしてマイクロUSBのとUSB TypeAの充電・データケーブルを100均に買いに走りましょう
↑この辺なんかもいけるんじゃないでしょうか?試したわけではないですが…
↑私が購入したでもいけました。この商品はツイッターで購入された方で初期不良(COMポートが開けない)が確認されています。おそらくこの商品にかかわらずマイコン関係は当たりハズレがあるので複数個ある商品を購入したほうが問題切り分けしやすいです。
Arduino IDEの導入とその前に!
[10/9 10/23 追記 重要]
ここまで読んでアレですがArduino IDE導入前に言っておきます。今回、スプラ投稿セット(下の方にあります)の中にあるSplabannerのアップデートを行いました。
アップデート内容は
ArduinoIDE導入なしでLeonardoマイコンに書き込める機能(試作)を実装しました
です。これによりArduino IDEの導入の必要がなくなりました。
マイコンなんて使わないし!ArduinoIDEとかわけわからん!
って人は試してみてください。エラーが起こった時などはツイッターで報告してもらえると検証する気になります!ArduinoIDEなしで行きたい人は
に飛んでください。解説動画は以下になります。
コードを見てカスタムしたい人は読み続けてください
————
ArduinoIDEはマイコン使う人にはド定番なんですが、触ったことない人はこれが敷居高いですよね。とても丁寧に説明している参考サイトはイカになります。しっかり読んで進めてください。
これタイミング悪くArduinoIDE 2.0が出たんですね。上の記事は1.8系のものなのでちょっと違うかもしれません。あとで検証してみます。検証するまでは1.8系でやっててください。まだダウンロードできますね
僕は以前からArduinoIDE1.8系でしたので、上の参考サイトでやっていきます。結構詳しく説明されていますので大丈夫と思いますが、ハテナと思った点を書いておきます
ボードマネージャで「Arduino AVR Boards 1.83」のインストールとありますが、後でboards.txtを変更するときに1.82というフォルダがないと思うのでバージョン選択で1.82と1.83を両方インストールして1.83を適応(選んどけばよい)させるといいと思います。まぁ1.82でも動きましたけどね。
ちなみにboards.txtを書き換えると思いますが、この辺を切り替えているといつの間にか変更前に戻されてしまうのでleonardに書き込み前に今一度確認しておいた方がよさそうです。プログラムがleonardに正常に書き込まれているのにスイッチで認識しないという症状はboards.txtが戻っているか、書き換えをミスっているかの可能性が大きいです。
あとライブラリがらみのエラーでNintendoSwitchControlLibraryを入れてArduinoIDEを起動したり、検証・コンパイルしたりするときに
Missing ‘paragraph’ from library
ってメッセージが表示されてました。コンパイルは無事に通っているようですが気持ち悪いです。どうやら、
NintendoSwitchControlLibraryライブラリプロパティファイルのparagraphの項目が無いよ
と言っているみたいです。
C:\Users\<ユーザー名>\Documents\Arduino\libraries\NintendoSwitchControlLibrary\library.properties
のファイルを開いて
1 2 3 4 5 6 7 8 9 |
name=NintendoSwitchControlLibrary version=1.3.0 author=lefmarna maintainer=lefmarna sentence=A library for microcontrollers that uses Arduino to automate Nintendo Switch games. paragraph=A library for microcontrollers that uses Arduino to automate Nintendo Switch games. category=Device Control url=https://github.com/lefmarna/NintendoSwitchControlLibrary architectures=* |
paragraph=A library for microcontrollers that uses Arduino to automate Nintendo Switch games.
を付け加えてあげれば出なくなりますよ。
参考サイトにあるサンプルコードを張りつけてマイコンに書き込み、スイッチにつないで、自動でボタン操作が始まればOKです。つなげるときにコントローラー認識画面に変わりAを押せとか言われるので、下のサンプルコードのほうがいいかもしれません
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
#include <NintendoSwitchControlLibrary.h> void setup(){ pushButton(Button::A, 500, 10); } void loop(){ pushButton(Button::X, 600); pushHat(Hat::RIGHT, 200); pushHat(Hat::DOWN, 200); pushHat(Hat::LEFT, 200); pushHat(Hat::UP, 200); pushButton(Button::X, 600); } |
ここまでできないと次へは進めませんので頑張ってください。でもここまでくれば誰でもできます。
ドット打ちのコード
いつも通り最初に張り付けます。初心者は読み飛ばしOKです
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 |
#include <NintendoSwitchControlLibrary.h> #include "bmpdata.h" //現在の座標の保持変数 int x_pos = 0; int y_pos = 0; //終了したかどうかのフラグ bool finFlag = false; //Splabannerからの引継ぎ変数、SetUpでロードする uint16_t PRESS_WAIT_TIME = 30; //ボタン押したあとのウエイトタイムms uint16_t RELEASE_WAIT_TIME = 30; //ボタン離したあとのウエイトタイムms uint8_t A_PUSH_COUNT = 10; //接続したときに押すAボタンの回数 uint8_t OVER_PUSH_COUNT = 10; //ズレ防止のために余剰に左右に動かす回数 bool FINISH_SAVE = true; //打ち終わったら保存するか //bmpデータから指定座標のドット情報の取得 true:白 false:黒 bool GetDot(int x, int y){ bool dot; uint8_t v = pgm_read_byte(&(Data[y][x/8])); //PROGMEMからのリード dot = false; if(x % 8 == 0) dot = (v & 0x80) > 0; if(x % 8 == 1) dot = (v & 0x40) > 0; if(x % 8 == 2) dot = (v & 0x20) > 0; if(x % 8 == 3) dot = (v & 0x10) > 0; if(x % 8 == 4) dot = (v & 0x08) > 0; if(x % 8 == 5) dot = (v & 0x04) > 0; if(x % 8 == 6) dot = (v & 0x02) > 0; if(x % 8 == 7) dot = (v & 0x01) > 0; return dot; } //ドット打ち void DotBlack(){ SwitchControlLibrary().pressButton(Button::A); SwitchControlLibrary().sendReport(); delay(PRESS_WAIT_TIME); SwitchControlLibrary().releaseButton(Button::A); SwitchControlLibrary().sendReport(); delay(RELEASE_WAIT_TIME); } //十字キーの入力 void pushHatEx(uint8_t hat){ SwitchControlLibrary().pressHatButton(hat); SwitchControlLibrary().sendReport(); delay(PRESS_WAIT_TIME); SwitchControlLibrary().releaseHatButton(); SwitchControlLibrary().sendReport(); delay(RELEASE_WAIT_TIME); } void setup(){ //Splabanner引継ぎ変数のロード //ウエイトタイムの初期値をロード PRESS_WAIT_TIME = pgm_read_word(&(Data[120][0])); RELEASE_WAIT_TIME = pgm_read_word(&(Data[120][2])); //Aボタンプッシュ回数 A_PUSH_COUNT = pgm_read_byte(&(Data[120][4])); //ズレ防止用プッシュ回数 OVER_PUSH_COUNT = pgm_read_byte(&(Data[120][5])); //書き込んだ後保存するか uint8_t f = pgm_read_byte(&(Data[120][6])); FINISH_SAVE = f > 0; //コントローラーの決定でAボタンを5回0.5秒ごと押す pushButton(Button::A, 500, A_PUSH_COUNT); //小さいペンに変える pushButton(Button::L, 500, 5); //ペン先を左上に持ってくる tiltLeftStick(Stick::MIN, Stick::MIN, 5000); //全面クリア pushButton(Button::LCLICK); } void loop(){ if(y_pos >= 120) { //打ち終わったら保存処理する場合 if(!finFlag && FINISH_SAVE){ //保存するのに念のためマイナスを0.5秒毎10回押す pushButton(Button::MINUS, 500, 10); finFlag = true; } return; //y_posが119行を超えたら終わり } bool dot = GetDot(x_pos,y_pos); //黒の時ドットを打つ if( !dot ) DotBlack(); //yが偶数の時は右へ 奇数は左へ if( y_pos % 2 == 0 ){ //偶数 if(x_pos >= 319 ){ //右端到達改行 for(int i=0;i< OVER_PUSH_COUNT ;i++) pushHatEx(Hat::RIGHT); //ズレ回避 y_pos++; pushHatEx(Hat::DOWN); }else{ //右へ進める x_pos++; pushHatEx(Hat::RIGHT); } }else{ //奇数 if(x_pos <= 0){ //左端到達改行 for(int i=0; i < OVER_PUSH_COUNT ;i++) pushHatEx(Hat::LEFT); //ズレ回避 y_pos++; pushHatEx(Hat::DOWN); }else{ //左へ進める x_pos--; pushHatEx(Hat::LEFT); } } } |
なんてことはない、ドット情報を左上から書き始めて左右走査して320×120を打つコードです。
少しだけ解説入れときます。
ドット打ち、十字キーには汎用関数のpushButtonを使っていません。なぜならライブラリのコードを見てみると入力後のウエイトタイムが100msで固定されているためです。これでは高速化ができません。ライブラリの固定値をいじろうかなと思いましたが、どうやらNintendoSwitchControlLibraryはSwitchControlLibraryのコマンドを使えるので、それでウエイトタイムを調整できるようにしています。
ズレ回避というのは、タマになんですがカーソル移動が引っ掛かりズレることがあります。1ラインドット打ち終了毎に10ドット程余計に移動させて次の行に影響でないようにしています。少しずれたところは後で手で修正すればいいですしね。10ドット以上ズレた場合は、後で説明するウエイト時間を調整した方がいいと思います。
[追記 10/23] —
ちなみにウエイトタイムは以前のバージョンでは定数としてbitmap.hで宣言するようにしていましたが、ArduinoIDEを用いないでleonardoに書き込む用のコードとの共通化のため、画像データの最後にくっつける感じで配列に内包されましたので注意してください
—-
ここまで読んだ人は
「で?画像データどうすんのよ?」
って話ですが、Arduinoには元来ファイルシステムという概念がないのでコード上に画像データを置く必要があります。上のコードでbmpdata.hがそれにあたります。次にbmpdata.hのデータを生成しなければなりません。
画像データ(bmpdata.hの内容)生成・コピペ
読み飛ばした人は、ここから読みましょうw。まずはspla投稿セット.zipを下からDLし展開します。ちなみにWindowsアプリですのであしからず。
最初にLeonardを接続し、spladraw.inoをArduinoIDEで開いてマイコンボードに書き込むを押してみましょう。書き込めましたか?書き込めないようであれば
ArduinoIDEの導入に戻って上のサイトを100回読んでやり直しましょう。問題なく書き込めた人は下へ行きます。
まずは白黒(2諧調) ビット深さ1bit(2色) 320×120サイズのBitmap(bmp)画像を用意しましょう。
——
[10/21補足]
Splabannerのアップデートで、大体のフォーマットと画像トリミング、二階調化の機能を実装しました。細かい修正などphotoshopやGIMPでできるように書き出し保存も実装済みです。詳しくは、上の新バージョンの説明動画を見てください。
少し時間があったので320×120のサイズの画像(bmp,jpg,png,gif)は読み込むようにしました。最新のspla投稿セットにはそちらが入っています。サンプル2.jpgも同梱しています。
ただし読み込みサイズは320×120のみです。拡大縮小機能つけると時間がかかりそうだったのでこれで勘弁してくださいw。また簡易2階調機能も付いていますが、あくまで簡易ですので、きれいに2階調化させたいとか、輪郭を抽出したいとかはphotoshopなどの範疇となるのでそちらでどうぞ。
ちなみに以前限定していた「bmp形式のビット深さ1bitの画像」は無変換でそのままロードしますので、ほかの編集アプリで作ったものはbmpの深さ1bitで書き出すとよいです。
——
フォトショップでもGIMPでもいいので320×120の画像を作ってください。ない人はサンプル.bmpが同梱されていますのでそちらで確認してください。素材は
からもらいました。
画像データをマイコンの中に入れるには変換作業が必要になります。Windows用ですがソフトを作りましたのでそれを使います。splabanner.exeを起動して画像読み込みを押しサンプル.bmpを選びます。
ちなみにネットから落としてきたexeを実行しようとすると
上のように怒られたりしますが、詳細情報をおして実行するを選べば実行できます。ウイルスは入っていませんが、どうしても怖い人はサンドボックス環境でどうぞ!ソースはDelphiで恥ずかしいのでさらしたくありませんw
ボタンを押したとき離したときの時間は自動打ちをするときのディレイです。短すぎるとドット落ちやズレの頻度が高くなります。20msで最初やってみてドット落ちやズレがひどいときは長くすればよいですが、長くすると描記時間が増えますのでご注意を。次にコード出力を押します。現在の新バージョンでは30msか既定値となっています。
また詳細設定で接続したときのAボタン回数、ドット打ち後の保存の可否、ズレ防止の移動量を設定できるようになっています。
エディターに表示した内容を、エディタ上で右クリックすべて選択->コピーをします。
[10/21 追記]
2階調化されていないbitmap.場合やjpg,gif,pngの場合は、誤差拡散法もしくは単純二階調化で、2階調1bitに変換するウインドウが出ますので適当にしきい値を調整して読み込んでください。
また輪郭抽出の機能も付けました。詳しくは上のYoutubeで確認願います。
320×120以外の解像度を読みこむとトリミング機能が動きますので、切り出したい部分を調整できます。こちらもYoutube動画で解説を入れてありますので参考にしてください。
マイコンボードへの書き込み・描記
またspladraw.inoをarduinoIDEで開きます。タブに、spladrawとbmpdata.hがあるのでbmpfata.hの中身を丸ごと先ほどコピーした内容に置き換えます
あとはLeonardoを接続しマイコンボードに書き込むを押すとOKです。コピペする前は書き込めたのにエラーが出るひとは全角スペースなどの文字が混入していないか調べましょう。だめなら、bmpdata.hを全部消して再度張り付けましょう。
スイッチでの使い方は、イラストの描記画面を表示した状態(カーソルはどこでもいい)からスイッチのUSBにLeonardoを指すだけです。
コントローラー認識画面が出てきて下の処理が始まります。
- 10回ほどAを押す
- ペンを一番小さくする
- カーソルが左上に移動する
- 全面クリアする
- ドット打ち開始
あとは待つのみとなります。コントローラー認識から進まないとかはUSB抜き差しするか、10回ほどAを押すのを20回とかに増やしてもいいかもしれませんね。2台のスイッチでやりましたが問題なく両方でできています。ちなみにドックで行った方が電池切れも心配もないですしUSB TypeAなので100均のケーブル(要データ用)が入手しやすいと思います。うまくいくと下のようにドット打ちをします
Arduino、Windowsでトータル開発時間2時間かからなかったのでよかった~。マイコン関係は大体、想定外のことが起きて時間が溶けるんですよね。