Python初心者がツムツムを自動化してみた
動作中の動画
なぜPythonなのか
恥ずかしながら今まで噂に聞くことの多いPythonに触れたことがなかったため、この機会に使えるようになっておこうと思ったのが動機です。
なぜツムツムなのか
ツムツム以外の他のゲームの自動化でもよかったのですが、ツムツムには他のゲームにない特徴があり、自動化するにあたってある程度の難易度があるため挑戦してみました。画像認識も、Pythonでの開発も初めてなので、腕試し目的です。
ツムツムの他のゲームにない特徴点
ツムツムには他のゲームにない特徴があります。
ざっくり言うとリアルタイム性とツムが回転・移動する点です。
自動化にあたって、この点に必ず悩まされます。
他のパズルゲームでは基本的に回転動作はなく、テンプレートマッチングによる検出のみで物体の認識が可能であり自動化は比較的に楽です。
しかしツムツムは移動と回転が組み合わさって非常に認識が難しいです。
開発環境
今回の開発にあたって使用した環境を載せておきます。
・Python 3.7.2
・Opencv 4.0.1
・anaconda3
・Nox Player 6.2.7.1
開発の流れ
本当はソースコードをそのまま載せたり、配布したりしたいのですが、
流石に色々と問題がありそうなので、最低限処理に必要なものを記載していきます。
質問があれば答えたりするかもしれないです。
ツムの認識
まずは、ツムを認識しなければ話になりません。
認識手法としては以下のものを試しました。
1.輪郭検出からの最小外接円算出
2.watershedアルゴリズムによる物体の切り離し
3.ハフ変換による円検出
4.ディープラーニングによる物体認識
現在、最終的には「3.ハフ変換による円検出」でツムを認識しています。
認識精度は「4.ディープラーニングによる物体認識」が一番よかったですが、新しいツムを引くたびに学習データを作るのがめんどくさかったので…。
ツムの判定
ツムの認識ができたとしても、最終的にツムをなぞる必要があるので、それがどのツムなのか判定できなければ意味がありません。
今回はわかりやすく色で判定を行いました。
色判定は、ハフ変換で検出した円の中心点からnピクセルの範囲をクロップし、画素情報の平均化を行った結果をその円の色としています。
そのままでは精度が悪いので平均化した画素情報は1の位を切り捨てています。
ツムのグループ化
グループ化は最終的になぞる経路の道しるべとなるものを設定する工程です。
ツムの判定で取得した色情報から、ある程度の閾値でグループ化します。
経路探索
グループ化が完了したら、経路探索用の処理を実装します。
今回はとりあえず動くものが作りたかったので、経路を探索する再帰関数を作成しています。
…非常に効率が悪いです。
経路探索の際は、距離の閾値と角度の閾値を設けると綺麗な経路が出来上がると思います。取得した経路はイメージに出力すると分かりやすいですね。
実際のゲーム画面で確認
実際のゲーム画面を取り込みます。
今回はNox Playerでツムツムをプレイし、 PILを使用してデスクトップキャプチャーを作成し、確認を行いました。
Python初心者のためここで型変換エラーに悩まされましたが、1つずつトラブルシューティングすれば動くようになります。
なぞる処理、スキル押下処理
PyAutoGUIを使用しています。
使い勝手がいいので特に詰まることもないです。
1点あげるとしたらデフォルトで処理に待機時間が設定されているので、高速でマウス操作を行いたい場合、「pyautogui.PAUSE = 待機時間」を設定しなおす必要があります。
私は0.03を指定しています。
その他追加した方がいい機能
ここまでの説明でツムツム自動化について最低限必要なものは簡単に説明が終わりました。
ツムツムにさらに特化させるべく、私は以下の機能を実装しています。
・マイツム優先処理
・ スキル連打、ボムキャンセル機能などのテクニック部分
・もう少しでフィーバーが終わる場合に、スキル発動を待つ機能
・ ハート自動送受信機能
どれも画像認識処理の組み合わせで実装できます。
しかしながら画像認識なので、100%動作するとは限らないところがポイントですね。
最後に
とりあえず形になってよかったです。
画像認識や物体認識など、これまで手を出していない分野に手を出してみるのは刺激になって楽しいですね。
これからも色々なことに手を出してみたいと思います。
2023/06/16追記
以下の記事にて円の検出と最長経路の探索方法を記載
ディスカッション
コメント一覧
スキル連打、ボムキャンセル機能などのテクニック部分
こちらについてお伺いしたいです。
パラメータ調整により、スクショから経路探索、マイツム優先までは実装完了していますが、
ボムの判定をどうしようかと悩み中です
ボムの認識については、別途画像認識の技術を利用して判定していますでしょうか?
コメントありがとうございます。
ボムの判定につきましては、ボムはツムに比べて完全な円であること、サイズが固定であることを利用してハフ変換で検出しています。検出する際のパラメータを調整することでボムのみ検出できるはずです。
サイト拝見させていただきました!
デスクトップキャプチャーは具体的にどのように行っていますか?
私は、マウスカーソルを取りたいスクリーンショットの右下と左上でエンターを押し、範囲を指定していたのですが、、、
また何秒間隔でスクリーンショットをしましたか?
ゲーム中の画像を1枚用意してその画像に対して経路探索が行えるところまで作成できたのですが、そのあとが難しいです。
コメントありがとうございます。
PILというライブラリでPC画面のキャプチャーを取得可能です。
ゲーム画像を1枚用意しての処理は作成済とのことなので、現在手動で用意している画像をPILで取得した画像に差し替えればよいです。
PILで取得した画像に対して処理を行う→再度PILで画像を取得して処理を行う。という流れを繰り返すことで常に最新状態の画像に対して処理を行いデスクトップキャプチャーを実装しています。
そのため、質問にある何秒間隔という設定はしていません。1枚目の処理を終えたらすぐ2枚目の処理というイメージです。
コード拝見しました。
「Nox Playerでツムツムをプレイし、 PILを使用してデスクトップキャプチャーを作成し、確認を行う」というのはスクリーンショットをたくさん撮るということですか?
少しだけヒント頂けると嬉しいです。
また、デスクトップキャプチャーを作成と自動化の工程は同時に行うのでしょうか?
コメントありがとうございます。
ご想像のとおり、デスクトップキャプチャーは画像の連続体なのでたくさんスクリーンショットを撮るイメージです。
工程としてはまず、ゲーム中の画像を1枚用意してその画像に対して経路探索が行えるところまで作成します。
その後、入力データとしていた画像をPILのgrab関数で取得したゲーム画像に変更して、選択処理(なぞる処理)を作っていきます。
あとは処理が終わるたびに新しくゲーム画面を取得して再度処理を流すのを繰り返せばOKです。
marimo様
こんにちは。
ブログと動画を拝見させて頂きました。
正直な感想として、本当に素晴らしいスキルで驚きました。
私自身、ツムツムはもう5年以上前からやっているのですが、Pythonは最近始めたばかりでまだまだ勉強中のため自動化までは程遠いです。
そこで、いきなりで恐縮ですが、ツムツムの自動プレイをPythonで行う方法を教えていただけないでしょうか?
もちろん勉強代も払わせて頂きます。
コメントの返信では書きにくいと思うので、メールでの返信をお待ちしております。
以上、よろしくお願い申し上げます。
この記事の本題とは外れますがハート送信を自動化するうえでハートが送られているかそうでないかの判定はどのようにしていますか?
コメントありがとうございます。
実装方法はいくつかありますが比較的簡単なハート送信処理の流れを記載しておきます。
まず画像認識で矢印付きのハート位置を検出できるようにしておきます。
次に検出した画像の中心付近をクリックし再度ハート位置検出しを行い同じ処理を繰り返します。
検出できなかった場合はスクロールを行い、再度ハート検出を行います。
そしてスクロールの処理が2連続で行われた場合には、一番下に到達したとして処理終了という流れです。
記事とは関係ないんですが、どのような勉強をしたらここまでのレベルになるのでしょうか?
やはり専門大学に行かないと無理なのですか?
ぷ自動化に興味のある初心者なんですが、なにから始めたらいいか教えて下さい。
匿名さん
コメントありがとうございます。
私個人の意見ですが、勉強は独学でも問題ないと思います。
私自身はITの専門学校を卒業しましたが、就職に力を入れている学校で資格勉強が主だったこともあり、授業等でプログラムを作成することはほぼなく座学がベースでした。
※ただ入学する場所によってはプログラムを重視しているところもあると思います。
勉強方法や、何から始めるべきかとのことですが、
今はネット上に情報が充実しているので、とにかく調べるというのが手っ取り早いと私は思います。
「こんなことがしたい!」というイメージが出た時に実現する方法を調べて、またわからないことが増えると思うので更に調べて、というのを自分がわかる内容になるまで繰り返すという方法です。
ただ、有識者の方に教わる方が圧倒的に楽だと思います。
最近ではプログラミング解説動画等もあったりするので、そちらを見てみるのもいいかもしれませんね。
一番最初にプログラムを読み書きできるようになって、その後にネット上のサンプルプログラム等を参考にしながら自分の作りたいものに応用させていくという流れになると思います。