【Python】ダンガンロンパのガチャ(モノモノマシーン)を自動で回し続けるためのマクロを作る(Steam版)
ゲーム「ダンガンロンパ」にはモノモノマシーンと呼ばれるガチャガチャが存在しており、ゲーム内で得られるコインを投入することで仲間の好感度を上げるためのプレゼントアイテムを入手することができます。 Steam版では実績の一つに、このプレゼントを全種類集めるというものがあり、そのためには出現するプレゼントが全種類揃うまでひたすらガチャを回し続ける必要があります。 一度に投入するコインの枚数を増やすことで、プレゼントが重複する確率を下げることができるのですが、問題は一枚あたりの上昇確率が非常に悪く、結局一枚ずつ回すのが一番効率が良くなってしまっていることです。 ゲームをプレイしたことがある人には伝わると思うのですが、このガチャは非常にテンポが悪く、一度回すごとにおよそ7秒くらいの演出が入るため、上記の一枚ずつコインを投入するやり方では、たいへん手間がかかります。 適当に動画を見ながら作業していたのですが、あまりに面倒だったため、キーボードマクロを組んで自動で実行することにしました。
需要あるかわかりませんが、一応実行ファイル化してあります。 Danron_AutoGacha.exeをクリックするとウィンドウが表示され、qキーでマクロを実行します。 実行中は、再びqキーが押されるまでキーボードのsキー(矢印↓)とenterキーが約1秒ごとに押され続けます。 コインがなくなるまで回し続けるので、キリのいいところで終了してください。
以下は技術面の話です。
つまいづいた点
キーボードの入力イベントの取得
pythonでキーボードの入力イベントを取得するためにはmsvcrtが一番簡単っぽいのですが、これはwindowsでしか動かなかったり、別のウィンドウからの入力を受け付けないなどの難点があります。 今回は代わりににpynputを使用しました。
DirectInputへの対応
そもそも開発の経緯として、キーボードマクロを設定するフリーソフトは世の中に多く存在するので、最初はそれを使おうと思ったのですが、どれも簡単なマクロを実行するだけには高機能過ぎたり、うまく動かなかったりという点がありました。 最初はpyautoguiというパッケージを使って次のように簡単に書けると思ったのですが、
import pyautogui as pgui import time def do_loop(): is_doing = True while True: if is_doing: time.sleep(1) print("running") pgui.press('down') time.sleep(1) pgui.press('enter') if __name__ == '__main__': do_loop()
これだとキー自体は押されるのですが、実際のゲーム画面では動きませんでした。 要は入力方式の違いで、Direct Inputに対応させる必要があるみたいです。
上のコードは別クラスからの呼び出しだと動かなかったので、下のように変更しました。
tkinterのマルチスレッド化について
配布するためにtkinterでGUIを作っているのですが、tkinterでメインウィンドウを表示させるroot.mainloop()
を実行すると、それ以降のコードは実行されません。
並行して別の処理を行うためには別スレッドで処理を行う必要があるみたいです。
def process1(): while True: if is_running: key_inputer.input() def process2(): with Listener( on_press = on_press, on_release= on_release ) as listener: listener.join()
ただしこうすると、メインウィンドウを閉じてもバックグラウンドにプロセスが残り、マクロが終了されません。 ウィンドウを閉じたときはメインスレッドだけが終了され、他のスレッドは終了されないためです。 これを回避するためには処理用のスレッドをデーモンスレッド化する必要があります。
並行処理についてあまり詳しくないのでもう少し勉強する必要があると感じました。
おわりに
Steam上のコミュニティではAutoHotKeyでのマクロが紹介されており、それが動くならそちらを使用されたほうが無難です。
今回は練習のために自分で実装しましたが、Steamでの操作をマクロ化したいという方の参考になれば幸いです。