Switch版DEAD OR ALIVE Xtreme3 Scarlet (DOAX3S) 自動プレイ

  • このエントリーをはてなブックマークに追加

1. どんなスクリプト?

Switch版DOAX3Sを自動プレイしてくれるスクリプトです。
動作の基本はここと同じです。

Switchはリモートプレイ機能がないのでハードウェアでカバーしているため少しお金がかかります。
とりあえず、PS4版DOAX3と同じことはできるようになったので公開します。今後改良するかもしれません。

(1)仕組み

USB Video Class(UVC)対応のHDMIキャプチャからゲーム画面を読み取り画像解析を行い、ポッ拳コントローラを疑似したArduino Pro Micro経由でSwitchを制御します。

2. 用意するもの

(1) UVC対応のHDMIキャプチャ

自分が使ってるのはFEBON238Hですが手に入らなさそうなので、IO-DATAのGV−HUVCとか良さそうです。※動作保証はしていません。

【送料無料】アイ・オー・データ機器(I・O DATA) GV−HUVC UVC(USB Video Class)対応 HDMI⇒USB変換アダプター [キャプチャーデバイス] (GVHUVC)

(2) Pro Micro

Amzoznだとこれとか
ATmega32U4 5V 16MHz Arduino互換ボード (Leonardo)
Arduino Leonardo 開発ボード 超小型 USB ダイレクト ATmega32U4 ピンヘッダ付

楽天だとこれとか

created by Rinker
¥2,434 (2020/09/28 02:36:48時点 楽天市場調べ-詳細)

Pro Micro 3.3V / 8MHz Arduino互換マイクロコントローラ

(3) USBシリアル

お持ちでない場合は、これとかがオススメです。

(2) 実行プログラム

Switch_DOAX3S_autoPlay.zip
Switch_DOAX3S_autoPlay_20200318.zip
※ダウンロードサイトを挟みます
※本ソフトウェアは、NYSLです。文字通り、煮るなり焼くなり好きに使ってください。

3. 環境構築

(1) Arduino Pro Microのポッ拳コントローラ化

ここが一番の鬼門です。

takashiskiのブログ 様

おいら屋ファクトリー 様
https://blog.feelmy.net/control-nintendo-switch-from-computer

を参考にして構築します。

①Linux on Windows環境を構築
Microsoft Storeを起動し「ubuntu」で検索。

インストールする。

インストール後起動すると、ユーザ名/パスワードの設定を求められるので好きなものを登録。(Windowsのユーザ名とは関係ありません)
以下画像はユーザ名/パスワード設定後に再度起動した際の画面です。

②Switch-Fightstickをmake
必要なソフトウェアを追加します。

GitHubからコードを取ってきてmakeします。

上手くいけば、フォルダ内に「Joystick.hex」が生成されます。

③WinAVRをインストール
ここからWinAVRをダウンロードしインストール。

④Pro Microに書き込み
コマンドプロンプトを起動し、②で生成した「Joystick.hex」があるディレクトリに移動。
Pro Microをブートローダモードに変更し以下コマンドを実行。

コマンド内のCOMyyはPro Microをブートローダモードにした際のポート番号です。
Pro Microを普通にPCにつなぐとCOMxxで認識されますが、リセットすると8秒間だけブートローダモードになり、その時PC上ではCOMyy(≠COMxx)として認識されます。
詳しくはここを参照ください。

⑤系構築
Pro MicroをSwitchドックのUSBポートに接続。
Pro Microの「TX1」「RX1」「GND」をPCとシリアル接続。
HDMIケーブルとHDMIキャプチャを接続
HDMIキャプチャとPCをUSBで接続

⑥Python環境構築
Pythonをインストールします。
画面下部「Add Python 3.7 to PATH」のチェックは入れといてください。

Pythonインストール後、コマンドプロンプトから以下コマンドを実行しライブラリをインストール

4. スクリプトの設定

①GUI画面の設定
フォルダ内のstartScript.batをダブルクリックすると以下のウィンドウが立ち上がります。

左上の「Camera ID」はPCに接続しているHDMIキャプチャのカメラIDを指定します。
デスクトップPC等カメラが元々付いていないPCは「0」、ノートPC等カメラが元々付いているPCは「1」を取り合えず設定します。
Switchの画面が映らない場合はカメラIDが違うので、値を変更し「Reload Camera」ボタンを押して違うIDのカメラを開いてみてください。
左上の「COM Port」は、Pro MicroとPCをシリアルポートで繋いでいる番号を指定してください。

中央上の「Capture」は、左下のSwitch画面のキャプチャを撮り、現在の日付のファイル名で保存するボタンです。
右上「Show Preview」のチェックを外すと、左下のSwitch画面の更新が止まります。止めても止めなくてもCPU使用率はあまり変わらないので、そのまま(チェックをつけたまま)で問題ないです。

画面を閉じると「Camera ID」「COM Port」の設定がリセットされるので、「Camera ID」「COM Port」が確認出来たら「gui.py」の12, 13行目を書き換えるとデフォルト値を変更できます。

②育て終わった、又は、育てなくてもいいキャラを設定
設定に応じて「auto.py」の33, 34行目を書き換えます。
例1
‘erena’でプレイ中で、’marie’ と ‘kokoro’ はスキップする設定です。
‘erena’で一周終わったら、次の’marie’を飛ばして’honoka’のプレイが始まります。

例2
一人目のキャラ(‘kasumi’)から順に誰もスキップせずにプレイする設定です。

例3
‘marie’で永遠プレイする設定です。
skipCharaに’marie’以外を設定しています。

③その他の設定
設定に応じて「auto.py」の35, 36行目を書き換えます。(特に必要ないと思うのでそのままで問題ないです)

35行目は、同一キャラを何回連続でプレイし続けるかを指定します。

36行目は、連続プレイの何回目かを指定します。

5. 実行!

①ゲーム内表示画面の設定
1周キレイに終わっている(リザルト画面をみてタイトル画面に移行した直後でPRESS ANY BUTTONが表示されている)状態ならタイトル画面を表示
周回の途中ならMorning/Daytime/Evening/Nighttimeいずれかの行動選択画面を表示

②Startボタン押下
GUI画面左上の「Start」を押すと自動プレイが始まります。
プレイ中はGUI及び、コマンドプロンプト画面を最小化していても問題ありません。

「Start」を押すと、ボタンが「Pause」に変わります。
「Pause」を押すと、①の画面で動作が一時停止します。

5. 更新履歴

(1) 2019年5月1日
① 初版公開
(2) 2020年3月18日
① GUI表示用スレッドと自動プレイ用スレッドでキャプチャボードからの読み出しがバッティングし、opencv内でエラーが発生する事象を改修

  • このエントリーをはてなブックマークに追加

SNSでもご購読できます。

コメント

  1. マサ より:

    はじめまして。
    記事を読ませていただき質問したいことがありましてコメントを残させていただきます。

    Pro Microをポッ拳コントローラー化は恐らくできたと思うのですが、そのPro Microを使ってswitchを操作するやり方をお聞きしたくてコメントしました。

    たとえば単純にAボタンを一定間隔で入力するような場合です。
    どのようなアプリケーションを使用してどのような記述をするのかもわかりません。

    いろいろ調べながら勉強をしていきたいと思っているのですが任意の操作の仕方を紹介しているサイトがほとんどなく、今回記事とあまり関係のない場違いな質問となっていて申し訳ありません。
    いずれは画像認識も含め他のゲームで自動操作を成功させたいと思っています。

    こういったプログラムを一切作ったことのない素人からの質問ですので本当に初歩の初歩の質問となるかと思いますが、お時間のある時にでも教えていただけると助かります。

    よろしくお願いいたします。

    1. t.uchida より:

      返信が遅くなり申し訳ございません。
      すでに解決しているかもしれませんが、返信いたします。

      操作方法をまとめているサイトを私も見つけられなかったので試行錯誤しつつコードを書きました。
      任意の操作をしたいとなると、ソースコードを解読するのが一番手っ取り早いと思います。
      https://github.com/ebith/Switch-Fightstick/blob/master/Joystick.c

      36行目: sscanf(line, “%s %s”, t, c);
      にあるとおり、シリアルから半角スペースで区切られた文字列を読み込み、
      以降に続くif分を実行していくようです。

      PCからはボーレート9600でシリアル接続し、ソースコートが欲する文字列を送信すればOKです。
      動きを見るなら、Python等で書くよりも、Tera Termなどの方が確認しやすいかもしれません。

      例えば、Aボタンを入力したい場合、
       strcasecmp(t, “Button”) == 0)
      にマッチさせたいので、空白の前は「Button」を、
      次は、
       else if (strcasecmp(c, “A”) == 0)
      にマッチさせたいので、空白の後は「A」を打つ必要があるため
      「Button A」と送信すればOKです。

      ちなみに、変数「t」の文字列は以下の紐づきの様です。
      “Button”:ボタン入力
      “LX”  :LeftスティックのX軸(横方向)入力
      “LY”  :LeftスティックのY軸(縦方向)入力
      “RX”  :RightスティックのX軸(横方向)入力
      “RY”  :RightスティックのY軸(縦方向)入力
      “HAT” :十字キー入力

      1. マサ より:

        返信ありがとうございます。
        pro micro や python等全くの素人なのに興味を持ってしまって勉強しようにも勉強の仕方すらわからない状態でして・・

        最終的にはこの記事で紹介されているような状況判断し自動で同じことを繰り返すようなプログラムを作りたいのですが現状はpro microを動かすことすらできずにいます。

        ポッ拳コントローラー化は恐らくできていると思うのですが、先に質問した通り単純なコントローラー入力の方法すらもわからなかったので質問させていただきました。

        例えば1回Aボタンを押させる場合どんなコードを作成すればいいのでしょうか?
        windows10 python3.7 でコードを書いてみましたがエラーは出ませんが動かず。

        import serial

        ser = serial.Serial(‘COM5’,9600,timeout=None)

        ser.write(b”Button A”)

        ser.close()

        基礎すぎる質問ですが直すべきとところ、悪いところを教えていただけると助かります。

        1. t.uchida より:

          switchがポッ拳コントローラを認識しているか/いないかでコードが変わるのですが、
          認識していない状態で1回Aボタンを押すコードをコメント下部に記載します。
          コントローラを認識しているかどうかは、ホーム画面下部真ん中の「コントローラ」画面から確認できます。

          「Aボタンを押す」という行為ですが、「Aボタンを押し下げる」と「Aボタンを離す」という命令をセットで書く必要があるため、
          8行目でボタンを押し下げる命令を、10行目でボタン離す命令を出しています。
          9行目の100msのsleepは、命令間の間隔が短すぎると命令が取りこぼされることがあるため少し待っています。

          4~6行目ですが、switchがポッ拳コントローラを認識していない場合、何かのボタンを押してswitchにコントローラを認識させる必要があるため、
          変な動作が起こらないであろうBボタンを押しております。
          7行目の5sのsleepは、switchがコントローラを認識して操作可能になるまで少しラグがあるため5s待っていますが、
          こんなに待たなくても大丈夫だと思います。

          ——————–
          import serial
          import time
          ser = serial.Serial(‘COM5’,9600,timeout=None)
          ser.write(b”Button B\r\n”)
          time.sleep(0.1)
          ser.write(b”RELEASE\r\n”)
          time.sleep(5)
          ser.write(b”Button A\r\n”)
          time.sleep(0.1)
          ser.write(b”RELEASE\r\n”)
          ser.close()
          ——————–

          1. マサ より:

            詳しく説明ありがとうございました!!

            無事ボタン操作することができました。
            本当に助かりました。

            自分でさらに勉強してみたいと思います。

  2. もく より:

    お世話になっております。
    大変お手数ですが下記、ご教示頂けないでしょうか。

    上記の通り導入後、GUI上でCOMポート・カメラIDを入れるとゲーム画面は正常に映るのですが、startボタンを押下すると映像が停止し、下記エラーが発生し動作停止となってしまいます。

    [ WARN:1] global C:\projects\opencv-python\opencv\modules\videoio\src\cap_msmf.cpp (1113) SourceReaderCB::OnReadSample videoio(MSMF): OnReadSample() is called with error status: -1072873821
    [ WARN:1] global C:\projects\opencv-python\opencv\modules\videoio\src\cap_msmf.cpp (1125) SourceReaderCB::OnReadSample videoio(MSMF): async ReadSample() call is failed with error status: -1072873821
    [ WARN:0] global C:\projects\opencv-python\opencv\modules\videoio\src\cap_msmf.cpp (1159) CvCapture_MSMF::grabFrame videoio(MSMF): can’t grab frame. Error: -1072873821
    [ WARN:0] global C:\projects\opencv-python\opencv\modules\videoio\src\cap_msmf.cpp (1159) CvCapture_MSMF::grabFrame videoio(MSMF): can’t grab frame. Error: -2147483638

    ちなみにキャプチャを使用しない別プログラム(Aボタン連打等)では動作確認済のため、Arduino 経由でのSwitch制御は問題ないかと思います。

    何か思い当たる要因等ありましたら、ご教示頂けると助かります。

    1. t.uchida より:

      調査してみたところ、キャプチャボードを複数スレッドで同時に読み出しているのが原因の様でした。
      プログラムの内部では、GUI表示用と自動プレイ用でスレッドを分けています。プログラム起動後からstartボタンを押すまでの間はGUIのスレッドのみが動作しておりキャプチャボードからの読み出し結果を表示しています。startボタンを押すと自動プレイ用のスレッドが立ち上がり、そちらでもキャプチャボードからの読み出しを始めます。
      この2つのスレッド間で読み出しがバッティングすると記載いただいたエラーが出る様です。

      改修版として、自動プレイ用スレッド内ではキャプチャーボードからの読み出しを行わないようにし、代わりにGUI表示用スレッドで読み出した結果を自動プレイ用スレッドに渡す、との処理に変えたプログラム (Switch_DOAX3S_autoPlay_20200318.zip) をアップロードしましたので動きを見ていただけますと幸いです。

      1. もく より:

        修正プログラムで実施したところ、エラーが発生しなくなりました。
        お忙しいところ早々にご対応頂きまして誠にありがとうございました!

        重ねての質問で大変恐縮なのですが、起動はするようになったものの行動画面でプール選択後、ぴょんぴょんゲームが選択されず、上下カーソル移動のループが発生する事態に陥ってしまいました。
        また、タイトル画面から開始する場合は、キャラ選択画面までは動作しますが、[kokoro] Can’t detect itemとなり進まない状況となりました。

        PS4版のスクリプトにおける質問回答を参照したところ、おそらくは解像度関係の問題かと思いますが、リモートプレイとは違い本スクリプトでは画面サイズ固定のため、Windows自体の解像度かSwitchのテレビ出力解像度の設定が関係するのでしょうか。
        ※Switchのテレビ出力設定は1080p、720p等試しましたが改善されませんでした

        私の環境ではWindowsの解像度は1920×1080、スケーリング100%となっております。
        また、キャプチャボードはIO-DATA GV−HUVCです。

        お忙しいところ大変申し訳ありませんが、何か思い当たる事項等ございましたらご教示頂きたくお願い申し上げます。

        1. t.uchida より:

          ご確認いただきありがとうございます。
          記載いただいたようにSwitchのテレビ出力解像度が影響している可能性もあるかと思います。こちらの開発環境では、Switchのテレビ出力解像度を1080p(固定)にしているため、1080p(固定)にしていただいた方が確実かと思います。
          思い当たるとすると、Switchの[設定] > [テレビ出力] > [画面の大きさを調整] は100%になっておりますでしょうか。
          画像認識用の画像は、画面周囲に黒枠が無くかつ見切れてもいないぴったりサイズの状態で取得しているため、アンダースキャンorオーバースキャンの状態で動作させると正常に動かないかと思います。

  3. もく より:

    確認遅くなりまして申し訳ございません。
    上記、確認したところ、解像度1080p固定かつ「画面の大きさを調整」が100%となっておりました。
    試しに100%と99%で確認したところ、100%の場合は、プールは選択されるがぴょんぴょんゲームが選択されず、99%の場合はプールも選択されない状態となりました。
    そのため、おそらくぴょんぴょんゲーム選択のためのimgファイルが、uchida様の環境下と微妙に異なり認識されないのではないかと思います。
    今週末にでもこちらの環境下で画面キャプチャし、ぴょんぴょんゲーム選択のimgファイルを差し替えて試したいと思います!

コメントを残す

*