※本記事は、ポケモンBDSPのポケモンコンテストでのリボン付与を自動化するプログラムについて解説した記事です。ポケモンBDSPの操作をArduino Leonardoで自動化しております。「Arduinoって何?」って方は剣盾の00回目の記事を、Arduinoの環境構築(ライブラリ含む)は01回目の記事をご覧ください。
本記事では、このプログラム(スケッチ)でできることや原理を解説したうえで、スケッチを配布しています。とにかくスケッチが欲しいという方は下へと読み飛ばしてください。
きっかけ、動機
ポケモンHOMEのアップデートにより、剣盾に加えてBDSP、レジェンズアルセウスと相互にポケモンの輸送が可能となりました。BDSPでは剣盾よりも前の世代限定だった一部のリボンが復活しており、さらに新規コンテストリボンも追加されていることから、コレクション要素としてリボン集めがしやすくなりました。
今回は、リボン集めで手間のかかるコンテスト制覇を楽にしようと思い(楽になったとは言っていない)、コンテストのリズムゲームを自動化しました。効率は良くありませんが、作ってしまったので公開します。
ついでに、ブイズ進化系を連れたふれあい広場での木の実+ダイブボール集めも自動化したので、簡単なプログラムですが公開しておきます。
これで何ができるの?
あらかじめ作成した譜面データをもとに、ポケモンコンテストの6部門のリズムゲームを自動で周回します。ロード時間にばらつきがあるため、成功率は3回に1回程度となり、クリアするために5回ほどコンテストを繰り返すこととなります。
また、本体やソフトの種類などによりロード時間が多少変わるので、最初に使う際は自身の環境に合わせてズレの調整が必要となります。数匹にリボンを付ける程度であれば、ズレを調整する時間よりもリズムゲームを手動クリアする方が早いです。
実用性低めです。作ってしまったのだから仕方ない。
原理、おおまかな流れ
概要
本プログラムでは、
コンテスト受付>コンテストでリズムゲーム>結果発表(リボン付与)
を繰り返します。実行するコンテストの部門や回数はプログラムを改変して設定します。
コンテスト前の準備について
ポケモンコンテストでは、ビジュアル、ダンス、技の3項目が審査されます。そのうち、ダンスは自動化に成否が左右される一方、残る2つは事前の準備が必要です。
以下、自動化と関係なくコンテスト前に必要な準備を簡潔に触れておきます。
ビジュアル①:ポフィン作り、コンディション上げ
BDSPのポフィンは食べられる量に限度があるため、レベルの高いポフィンを作って効率よくコンディションを上げる必要があります。 ポフィンを作るための木の実の入手方法は以下の通り。
①各地で土に植えて育てる(リアル時間経過)
②ふれあい広場やフィールドでポケモンと歩き、ポケモンから貰う(ゲーム内歩数)
③木の実をくれるNPCから貰う(1日1回、3箇所)
④208番道路(ヨスガ左)で購入する(No.1-5の木の実)
⑤その他、ものひろいのポケモンが拾ってくる、野生ポケモンが持っているなど。。。
動画中では、①で努力値下げ木の実を手動回収、②ふれあい広場でポフィン専用木の実自動回収、④状態治し木の実購入をすることでLv70程度のポフィンを作成しています。
②ふれあい広場での回収については、ブイズ進化系(サイズ1.5マス程度)6匹を連れた状態で使用できる自動化を作成しましたので、ついでに公開しておきます。 ポフィン作成時に懐いたポケモンとふれあい状態であれば質のいいポフィンができやすくなるので、なつき度を上げるためにも自動回収をおすすめします。
なお、シャワーズを連れて行けば、木の実だけでなくダイブボールを拾ってくることがあります。
Lv70くらいの動画中のポフィンであれば3個で1つのコンディションがMAXとなりました。5つのコンディションをすべて上げてください。また、けづや(食べられる上限値)も評価に影響するので、コンディションを上げ終わったら適当にポフィンを与えてけづやもMAX(=これ以上食べられない状態)にしてください。
ビジュアル②:ボールカプセル
ビジュアル審査では、ポケモン自身のコンディションやけづやの他、ボールカプセルも重要となります。かっこよさ、うつくしさなどの部門ごとにシールが対応しているようなので、対応するシール20枚を貼り付けます。(対応シールについてはググってください)
自動化では、部門に応じて以下の場所のボールカプセルを選択するため、それぞれの部門に相性の良いシール20枚ずつを貼ってください。
上段 左から かっこよさ、うつくしさ、かわいさ、かしこさ、
2段目左から たくましさ、ブリシャイ。
技=ポイントの高くなるものを。
BDSPのダンス審査中に1度だけ、あらかじめ選択した技を出してアピールすることとなります。ポケモンの覚える技ごとにアピールポイント♡や追加効果が設定されています。できるだけポイントが大きくなる技を覚えさせ、1番上に配置してください。自動化中は1番上の技を選択します。最強技はギガインパクト。
自動化中のダンス審査の動作について
自動化では、あらかじめ設定した部門のマスターランク、手持ち1番上のポケモン、技、部門ごとのボールカプセルと順に選択を行い、ダンス審査へと移ります。
プログラムでは、6部門それぞれのダンス審査の曲のBPM、譜面データをあらかじめ作成しております。 設定したBPMから1拍の時間(4分音符)を計算し、その半分の時間(8分音符)ごとに譜面データを読み込み、Aボタンを押したり長押ししたり、コンテスト技を使用したりを行います。
例えば、かっこよさコンテストの場合、
const int bpm_cool = 100; によりBPM=100、
つまりは1拍は 60秒÷100=0.6秒 となります。
譜面データ(char score_cool)の0、1、2などの数字1つが半拍の0.3秒となっており、「1:Aボタンを押す」「0:何もせず待機」「50:コンテスト技を使用」といったような動作を譜面通りに読み込みます。数字ごとの命令についてはスケッチ内「void contestDance」参照。
<重要>ダンス審査のズレの調整について
ダンス審査は、上記に説明したように譜面データを順に読み込むことで動作します。
その譜面の開始地点については、コンテスト開始時のロード時間に依存して変わります。おそらく、使用しているSwitchが新型か旧型か、ソフトがパケ版かDL版か、などの環境により多少のズレが生じます。今回は画像認識などを使用していないため、そのタイミングを自身で設定する必要があります。(ただし、完璧に合わせようとしてもロードごとに0.5秒程度はずれるため、何度か動かした平均をもとに設定します。)
初期設定は、有機ELでない電池改善後Switchとパケ版SPの組み合わせで実行した際のものとなります。
設定する箇所は、以下の2か所となります。
const int visual_time = 15410;
コンテスト衣装を選んだ直後から、ダンスの最初の音符を叩くまでの時間は約30秒となります。visual_timeには、その時間-15秒を設定します(単位:ミリ秒)。
動画を参考に、タイミングのズレを調べ、まずはここを調整してください。数値を増やせば叩くタイミングが遅くなり、減らせば早くなります。
const int offset_cool = -200; (部門ごとにoffset_○○)
上記のvisual_timeを設定することで、6部門すべての時間を調整することができます。一方でこのoffset_○○は部門単体での時間のズレを調整するための数値となります。かっこよさをvisual_timeで合わせた後、うつくしさでタイミングが合わないなどの場合に調整してください。
また、譜面データについて、0.3秒程度の短時間ごとに命令を区切っていることから、わずかなズレが積み重なることで曲の後半にタイミングがずれていきます。その対策として、譜面内で「8:通常より0.01秒多く待機する」「9:通常より0.01秒多く待機する」という命令を用意し、「0:何もせず待機」の代わりに配置することで強引に対処しています。
可能性は低いですが、マイコンごとの個体差によりズレが異なる可能性があります。その場合、譜面データ内の0、8、9の配置を調整してください。
準備、必要なもの
本スケッチでは、マイコンを挿す前に以下の準備が必要となります。
初期条件は以下の通り
1.コンテストの各部門(ブリリアント・シャイニング含む)のノーマル、グレート、ウルトラまでをクリアしておき、マスターランクに挑めるようにする。
2.コンテストに挑むポケモンにポフィンを与え、すべてのコンディション、けづやを高める。けづやも評価に影響するため、高レベルポフィンを与えてコンディションを上げた後、適当なポフィンでけづやを上げる。
3.使用するポケモンを手持ちの1番上に配置し、効果の高いコンテスト技を技リスト1番上にする。覚えられるのであればギガインパクトがおすすめ。
4.ボールカプセルを各部門ごとに設定。ボールカプセル選択画面の最上段、左から順にかっこよさ、うつくしさ、かわいさ、かしこさ、上から2段目、順に たくましさ、ブリシャイ に使用するボールカプセルを設定。部門にあったシールを20枚貼り付けてください。
5.コンテスト会場、受付(中央)を向いた状態でレポート。その後、メニューを開き、カーソルをトレーナーカードに合わせておく(ブリシャイに参戦できなかった場合の誤作動防止のため)
6.以下の設定項目より、かっこよさマスターランクのタイミングが一致するように時間を調整する。はじめに初期設定でマイコンに書き込んで開始し、速いか遅いかを元に調整する(詳しくはスケッチ内の設定項目を参照)
7.以上の準備を終えたら、本スケッチを書き込んだマイコンを挿してスタート。初期設定ではすべての部門を5回ずつ行い、その後ブリリアントシャイニングコンテストを繰り返す。編集したい場合はスケッチ下側のvoid setup/loopを編集。
作成したスケッチ
作成したコンテスト自動化のスケッチはこちら。要時間調整。
おまけとして、ふれあい広場でのきのみ、ボール集め用プログラム(ブイズ進化系連れあるき)はこちら。
広場左下のフェンス脇に立ってマイコンを挿せば、広場を走り回り、約500歩ごとにアイテムを受け取ります。
本スケッチを実際に使用した動画はこちら↓
* BDSP用、コンテストマスターランク6種類の優勝によるリボン回収を自動化
* ロード時間の違いによりズレが生じるため、使用する本体・ソフトごとに時間調整が必要
* おそらく画像認識を使う方が確実。というか数匹程度であれば手動でやった方が早い。
*
* 初期条件は以下の通り
* 1.コンテストの各部門(ブリリアント・シャイニング含む)のノーマル、グレート、ウルトラまでをクリアしておき、
* マスターランクに挑めるようにする。
* 2.コンテストに挑むポケモンにポフィンを与え、すべてのコンディション、けづやを高める。
* けづやも評価に影響するため、高レベルポフィンを与えてコンディションを上げた後、適当なポフィンでけづやを上げる
* 3.使用するポケモンを手持ちの1番上に配置し、効果の高いコンテスト技を技リスト1番上にする。
* 覚えられるのであればギガインパクトがおすすめ。
* 4.ボールカプセルを各部門ごとに設定。ボールカプセル選択画面の
* 最上段、左から順にかっこよさ、うつくしさ、かわいさ、かしこさ、
* 上から2段目、順に たくましさ、ブリシャイ に使用するボールカプセルを設定
* 部門にあったシールを20枚貼り付けてください。
* 5.コンテスト会場、受付(中央)を向いた状態でレポート。その後、メニューを開き、カーソルをトレーナーカードに合わせておく(ブリシャイに参戦できなかった場合の誤作動防止のため)
* 6.以下の設定項目より、かっこよさマスターランクのタイミングが一致するように時間を調整する
* はじめに初期設定でマイコンに書き込んで開始し、速いか遅いかを元に調整する(詳しくは以下)
* 7.以上の準備を終えたら、本スケッチを書き込んだマイコンを挿してスタート。
* 初期設定ではすべての部門を5回ずつ行い、その後ブリリアントシャイニングコンテストを繰り返す。編集したい場合はスケッチ下側のvoid setup/loopを編集。
*/
#include <auto_command_util.h>
// 以下、設定項目--------------------
// [衣装を選んだ直後~ダンス開始、かっこよさコンテストマスターランク最初の音符が出るまでの時間]-15000(ミリ秒)の値を入力(オーバーフロー防止)
// ロード時間に幅があり、読み込みごとに早いときと遅いときがある(有機でない電池改善版Switch、パケ版パールの組み合わせの場合、15410程度)
// ブリリアント/シャイニングコンテスト以外はGREAT以上を出せていればだいたい勝てる。一方、ブリシャイはALL GREATでも負けることがある。
/* 以下、調整のコツ
* ①はじめにデフォルト15410程度でマイコンに書き込んで実行し、かっこよさコンテストでタイミングが早いか遅いかを判断する。
* かっこよさの音楽2小節目の2拍目(空白)のところでコンテスト技が発動するため、参考にする。
* 毎回時間のズレが異なり、ロード時間に0.5程度のブレ幅があるので、何度か確認して平均的に見てから早いか遅いかを判断する。
* ②以下のvisual_time を増減させる。タイミングが早ければ時間を増やし、遅ければ減らす。参考までに、1拍0.6秒(1小節=3拍)。
* ③ ②を繰り返してかっこよさコンテストが5回以内にクリアできるようであればOK。
* 続けて美しさ以降も自動で実行する。
* ④ プログラム初期設定であれば、かっこよさ~たくましさまで5回ずつ行い、1回ずつクリアできればそのままブリリアントシャイニングコンテストを繰り返す。
* もしいずれかの部門がクリアできていなければ、プログラムを書き換えるなどして個別に確認する。
* ずれていた場合、以下のoffset_coolなどを増減させれば、部門ごとに時間調整が可能。
*/
const int visual_time = 15410;
// 以下、コンテストの部門ごとにダンス曲のBPM、コンテスト開始からダンス開始までの時間のずれ、譜面データ
// 基本的にはそのままでいいが、ロード時間により部門ごとの時間が一致しない場合はオフセットを調整することで上記visual_timeの時間を個別に調整可能
// 譜面データの詳細は以下のcontestDance内を参照。
// BPMの1拍=4分音符、譜面を8分音符ごとに分割してAボタンを押す、長押しなどの指示を設定
// かっこよさマスターランク
const int bpm_cool = 100;
const int offset_cool = -200;
char score_cool[] = {
1,1,0,1,1,8,
1,1,50,1,1,0,
1,1,1,1,1,1,
1,0,0,1,1,8,
2,0,0,3,1,0,
2,0,0,3,1,8,
1,1,1,1,1,1,
1,0,0,1,1,8,
2,0,0,3,0,8,
2,0,0,3,8,8,
1,1,1,1,1,1,
1,0,0,1,1,1,
1,0,0,1,1,0,
1,1,0,1,1,8,
1,1,1,1,1,1,
2,3,1,1,1,1,
2,0,0,3,0,8,
2,0,0,3,0,8,
1,1,1,2,3,1,
1,1,1,2,3,1,
2,0,0,0,8,3,
1,0,0,0,1,2,
3,1,2,3,2,8,
3,1,1,1,0,0,
7,0,0,7,8,8,
1,0,7,1,0,0,
2,0,0,10,0,8,
1,1,1,1,1,1,
1,1,1,1,1,1,
2,0,0,3,8,8,
2,3,1,2,3,7,
1,1,1,2,3,1,
1,1,1,1,1,1,
2,0,3,2,0,3,
1,0,0,1,1,8,
1,1,1,1,0,0,
2,3,1,1,2,0,
3,1,2,3,4,0,
-1
};
// うつくしさマスターランク以下、割愛
// 以上、コンテストの部門ごとの設定
// 以上、設定項目--------------------
// BPMから算出される8分音符、16分音符の時間を定義する変数
int eighth_note_time;
int sixteenth_note_time;
// 実行するコンテストの部門から、ダンス曲のBPMと譜面データを定義
// その後、コンテスト受付に話しかけてコンテスト開始、終了して受付に戻るまで
void selectContest(char genre_num){
// コンテスト受付~参加する
pushButton(Button::A, 800, 6);
// 指定の回数だけカーソルを下に動かし、部門を選択(かっこよさ=0)
// かっこよさ、うつくしさ、かわいさ、かしこさ、たくましさ、ブリシャイ
pushHatButton(Hat::DOWN, 300, genre_num);
// 部門決定~どのランク
pushButton(Button::A, 800, 2);
// カーソルを下に動かし、マスターランクを選択
// ノーマル、グレート、ウルトラ、マスター
pushHatButton(Hat::DOWN, 300, 3);
// ランク決定~ポケモンを選ぶ~
// 手持ち1番上のポケモンの1番上の技を選択
pushButton(Button::A, 800, 2);
pushButton(Button::A, 1000, 4);
// 部門に対応してボールカプセルを選択
// カプセル1段目左からかっこよさ、うつくしさ、かわいさ、かしこさ
// 2段目たくましさ、ブリシャイ となるように部門ごとにカプセルを設定
pushHatButton(Hat::DOWN, 300, genre_num/4);
pushHatButton(Hat::RIGHT, 300, genre_num%4);
// ボールカプセル決定、衣装選択画面へ
pushButton(Button::A, 1000);
pushButton(Button::A, 4500, 2);
// Aを押したらコンテスト開始
pushButton(Button::A, 100);
// ここで、指定した部門ごとに音符当たりの時間を計算し、異なる譜面を読み込んで実行する
switch(genre_num){
// かっこよさマスターランク
case 0:
// 8分音符あたりの時間=BPM/60*1000/8 ミリ秒を定義
eighth_note_time = 30000/bpm_cool;
sixteenth_note_time = 15000/bpm_cool;
// コンテスト最初の音符まで待機30秒くらい
delay(14800);
delay(visual_time + offset_cool);
contestDance(score_cool);
break;
// うつくしさマスターランク
case 1:
// 8分音符あたりの時間=BPM/60*1000/8 ミリ秒を定義
eighth_note_time = 30000/bpm_beauty;
sixteenth_note_time = 15000/bpm_beauty;
// コンテスト最初の音符まで待機30秒くらい
delay(14800);
delay(visual_time + offset_beauty);
contestDance(score_beauty);
break;
// かわいさマスターランク
case 2:
// 8分音符あたりの時間=BPM/60*1000/8 ミリ秒を定義
eighth_note_time = 30000/bpm_cute;
sixteenth_note_time = 15000/bpm_cute;
// コンテスト最初の音符まで待機30秒くらい
delay(14800);
delay(visual_time + offset_cute);
contestDance(score_cute);
break;
// かしこさマスターランク
case 3:
// 8分音符あたりの時間=BPM/60*1000/8 ミリ秒を定義
eighth_note_time = 30000/bpm_clever;
sixteenth_note_time = 15000/bpm_clever;
// コンテスト最初の音符まで待機30秒くらい
delay(14800);
delay(visual_time + offset_clever);
contestDance(score_clever);
break;
// たくましさマスターランク
case 4:
// 8分音符あたりの時間=BPM/60*1000/8 ミリ秒を定義
eighth_note_time = 30000/bpm_tough;
sixteenth_note_time = 15000/bpm_tough;
// コンテスト最初の音符まで待機30秒くらい
delay(14800);
delay(visual_time + offset_tough);
contestDance(score_tough);
break;
// ブリリアント・シャイニーマスターランク
case 5:
// 8分音符あたりの時間=1000/(BPM/60*2) ミリ秒を定義
eighth_note_time = 30000/bpm_brishi;
sixteenth_note_time = 15000/bpm_brishi;
// コンテスト最初の音符まで待機30秒くらい
delay(14800);
delay(visual_time + offset_brishi);
contestDance(score_brishi);
break;
}
// ダンス終了後、受付前に戻るまで待機
delay(30000);
pushButton(Button::B, 300, 28);
}
// ダンス(リズムゲーム)を実行する関数
// 指定した部門のダンス曲の譜面データを受け取り、譜面の順に実行する。
void contestDance(char score_data[]){
// BPMの1拍=4分音符、譜面を8分音符ごとに分割してAボタンを押す、長押しなどの指示を送る
/*
* 0:何もしない、休止符
* 1:Aを押して離す、8分音符♪
* 2:Aを押しはじめ、長押し。その後はAを離すまで間には0を入力
* 3:長押していたAを離す。例えば...2, 0, 0, 0, 3 とした場合は2分長押し相当
* 4:16分ずらしてA入力。
* 5:16分ずらしてA長押しはじめ。
* 6:16分ずらしてA長押しおわり。
* 7:16分音符2回。
* 8:何もしない、ただし時間調整のため上記0よりも0.01秒長く待機する。譜面の時間ずれ調整用。
* 9:何もしない、ただし時間調整のため上記0よりも0.01秒短く待機する。譜面の時間ずれ調整用。
* 10:A長押し終わり+16分音符。
* 50:Xボタンを押し、技を使ってアピール。その後しばらくは音符は表れないため入力不要
* -1:コンテストのダンス終了。譜面データ最後に置くと譜面の読み込みを終了する(置かないとエラー)
*/
for(int i=0; i<400; i++){
switch(score_data[i]){
case 0:
delay(eighth_note_time);
break;
case 1:
SwitchController().pressButton(Button::A);
delay(sixteenth_note_time);
SwitchController().releaseButton(Button::A);
delay(sixteenth_note_time);
break;
case 2:
SwitchController().pressButton(Button::A);
delay(eighth_note_time);
break;
case 3:
SwitchController().releaseButton(Button::A);
delay(eighth_note_time);
break;
case 4:
delay(sixteenth_note_time);
SwitchController().pressButton(Button::A);
delay(sixteenth_note_time-50);
SwitchController().releaseButton(Button::A);
delay(50);
break;
case 5:
delay(sixteenth_note_time);
SwitchController().pressButton(Button::A);
delay(sixteenth_note_time-50);
break;
case 6:
delay(sixteenth_note_time);
SwitchController().releaseButton(Button::A);
delay(sixteenth_note_time-50);
break;
case 7:
SwitchController().pressButton(Button::A);
delay(sixteenth_note_time-50);
SwitchController().releaseButton(Button::A);
delay(50);
SwitchController().pressButton(Button::A);
delay(sixteenth_note_time-50);
SwitchController().releaseButton(Button::A);
delay(50);
break;
case 8:
delay(eighth_note_time+10);
break;
case 9:
delay(eighth_note_time-10);
break;
case 10:
SwitchController().releaseButton(Button::A);
delay(sixteenth_note_time);
SwitchController().pressButton(Button::A);
delay(sixteenth_note_time-50);
SwitchController().releaseButton(Button::A);
delay(50);
break;
case 50:
SwitchController().pressButton(Button::X);
delay(sixteenth_note_time);
SwitchController().releaseButton(Button::X);
delay(sixteenth_note_time);
break;
case -1:
i = 999;
break;
}
}
}
void setup(){
//画面起動
pushButton(Button::B, 300, 13);
/* 以下、かっこよさから順にすべてのリボンを回収するため、すべて5回ずつ繰り返し。
* 体感として3回に1回くらい優勝できるが、時間調整とロード運次第。
*/
// かっこよさからたくましさ、ブリシャイまで各部門を順に読み込み
for(int x=0; x<5; x++){
// 1部門あたり5回ずつ実行
for(int y=0; y<5; y++){
selectContest(x);
}
}
}
void loop(){
// selectContest(n)の括弧内に0~5の数字を設定すると、対応するコンテストを実行
// 0から順にかっこよさ、うつくしさ、かわいさ、かしこさ、たくましさ、ブリリアントシャイニング
selectContest(5);
}
最後に
本スケッチを使用することで、コンテストのマスターランク6部門を自動でクリアできます・・・が、その前の調整に時間がかかり過ぎました。時間調整を1度済ませた後も、5倍くらいの時間がかかるため、用途は限定的になりそうです。
画像認識でズレの調整ができるかもしれませんが、燃え尽きたので諦めました。
需要は少ないように思いますが、作ってしまいもったいないので供養しておきます。
プログラムの不備、改善点などありましたらコメントやお問い合わせからお願いいたします。
Arduino Arduino Leonardo (ピンソケット・ピンヘッダ実装済) 【A000057】 | ||||
|
https://gist.github.com/unkoer/41b82dbee1064e874a02640cb1dc85aa
返信削除こちらの記事を一部参考にさせてもらい、画像認識を使ったPoke-Controller MODIFIED用のスクリプトを書いて数十匹にリボン付けることができました。
改善点ですが、現在ボタン入力後のdelay(eighth_note_time);のように書かれている部分を、プログラム実行開始からの経過時間を使うと、ダンス途中でボタン入力部分の実行時間によるズレを考慮しなくて済むようになります。
あと知らなかったんですがブリリアント部門・シャイニング部門は曲も譜面も違うみたいですね。
活用していただきありがとうございます。
返信削除たしかに、プログラムの経過時間を取得した方がズレを考慮しなくて済みそうです(作り直す気力があるかは不明ですが)。
ブリリアント部門とシャイニング部門で曲が違うのは初耳でした。名前以外に違いはないのかと思っていました...。