ポケモン対戦アシストツールを作りたい 進捗報告
お久しぶりです。たかぎです。
しばらく更新していませんでしたがPythonで遊ぶ企画はサボっていたわけではありませんよという報告です。
UIはこれから詰めていくとして、今のところ完成している機能は以下の通り
・自分のパーティーの登録機能
・選出画面での相手のパーティーの自動読み取り
・選んだポケモンの種族値、特性の表示(以外と特性忘れることありますよね)
・自分のポケモンの技を選ぶと相手の型に応じたダメージ早見表の表示
・すばやさ比較タブで相手の振り方(最速、無振り、下降など)とランクに応じた素早さ実数値の表示して、自分のポケモンとの比較できる(自分S+2と相手の最速+1どっちが早いかなどがすぐ分かる)
・対戦中の相手のHP残量の読み取り
・相手のアイコンの横のボタンを押すと読み取ったHPを保存
「細かい融通は利かなくてもイイから対戦中に欲しい情報を迅速に得られる」をコンセプトにすすめています。正直おままごとのような完成度ですが遊びと勉強両方を兼ねて楽しみながらやっています。開発に時間がとられてランクマッチ潜る時間が減ってるのは本末転倒。
今後の予定としては
・ポケモンHOMEの情報が見られるようにする
・ダメージ計算の各種とくせい、もちものetcの実装を順次進める
・使用率の高い技はワンクリックで表示できるようにUIの改善
・確定、乱数何発かの表示(今は1発で落とせる可能性のみ表示できる)
などを考えています。他にもこんな機能があったら便利そうってのがあればコメントで教えて貰えたら喜びます。
すこし話はそれますが、対戦中に外部ツールのアシストを受けることがフェアかどうかという議論はあると思います。ただし「ツール自体には善も悪も無い」というのが持論なのでそのあたりは気にせず開発は進めるつもりです。細かい考えについてはいずれまた詳しくかければなと思います。
【備忘録】Ttkinterでボタンを押した時にフォーカスを別のウィジェットに移す
またアプリ作成で躓いたので備忘録です。
あるボタンを押した時にフォーカスをcomboboxに移したかったのですが<ButtonPress>をイベントにしてfocus_set()を叩いてもフォーカスが移りませんでした。
調べても理由が分からなかったんですが、ボタンを押してフォーカスが移ったあとに再度ボタン側で何かしらの処理が起こってるのかなと推測してイベントを<ButtonRelease>にしたら上手く行きました。おそらくリリース時にもイベントが発生していてその際に再度ボタンにフォーカスが移動してしまったんだと思います。単純な話でしたがこれも調べてもなかなか出てこなかったので備忘録として置いておきます。
(これで1日躓いてた)
こんなばっかでマジで時間の無駄なのでChatGPTにコード書いてもらうことについて検討を加速させていくことを検討します。
ポケモンSV選出画面のpng画像素材詰め合わせ
ポケモンSVにおける選出画面での自分の手持ちおよび相手のPTのポケモンの画像をキャプチャしてトリミングしたpng画像の詰め合わせです。自分がアンチ720p派(ツール使うたびに切り替えるのが面倒くさいという理由)なので1080p用です。テンプレートマッチング用あるいは単純な画像素材としてご利用下さい。
ポケモンの英語名がファイル名になっています。各ポケモンの英語名を利用していますが、姿違いやフォルム違いについては調べるのが面倒だったので独断と偏見で命名しています。_(アンダーバー)ですがた違いを区別しているので同一ポケモンとして認識させたい場合はそのへんでなんやかんやして下さい。
以下現在分かっている不具合(?)
・アイコンが小さい一部のポケモンで一致率が上がりにくい(テツノカイナ等
→閾値で認識するのではなく「一致率が一番高いポケモンとして認識する」等で回避可能です
・自分のポケモンを認識する時は選択時に背景が黄色になってしまうので上の画像のようにカーソルを関係ない場所に置く必要がある
・キャプチャ環境の違いのせいで色味が微妙に違う可能性がある
→テンプレートマッチングに使う限りにおいては十分な一致率が出ているので気にしません。
ぜひどんどんご利用下さい。ここ間違ってるよとかこんな使い方したらなんか上手く行きませんでしたとか色々あったら教えてもらえると助かります。その他なにか個別のご質問・ご要望等あればお知らせ下さい。
以下リンクです
自分のPT:
相手のPT:
注意!:本画像の著作権は任天堂株式会社、株式会社ゲームフリーク、株式会社クリーチャーズに帰属します。商用利用に当たっては任天堂が公開しているガイドラインに準拠する必要があり、基本的に一部のサイト(YouTube等)での収益化以外は認められておりません。商用利用にあたり私に許可を取る必要はありませんが、一声かけていただけると純粋に喜びます。また、画像の私的な利用・改変は自由ですが再配布はお断りします。必ず当ページをリンクする形でご利用下さい。また、予告なく配布を終了する可能性がございます。
これ作るためにノココッチのみつふし出しましたがふたふしと画像一緒でした誰かなぐさめてください。種類多い+小さい+出にくいフラベベお前は許さない。しおさんポケモン提供ありがとうございました。
追記:
ゲッコウガ、エースバーン系統が入っていません。気が向いたらそのうち追加します。
追記2:
ポケモンGOとの連携で世界各国のポストカードに対応した模様のビビヨンが出るそうですが現状集めるのが無理ゲーなので協力者募集中です…
日記 進捗報告
こんばんは、たかぎです。今日もPythonで遊んでます。
ツール開発状況ですが
・選出画面を待機して対戦が始まったらHPの測定を開始、コマンド選択画面になるごとに毎ターンHPの残量表示を更新→完成!
・対戦終了、再開ボタンの作成→tkinterのafter関数とスレッドの関係が理解できておらず沼りましたが何とか実装できました。まじで死んでました。
・相手のptを自動で認識して対応したポケモンの情報と紐づけ
→認識機能ほぼ完成しました。何故かテツノカイナが正しく認識できないせいでかなり回りくどい方法を取らざるを得なくてなんか頭悪い処理になりましたが動くようにはなりました。
こうやって書くと大して進んでないですが中の人はめっちゃ苦労してます。
ここからは追加したい機能
・ポケモンの名前ー種族値等の情報は用意してあるので紐づけして表示出来るようにする。
・自分のptを登録しておけるようにする
・紐づけした情報から相手の主要な型に対するダメージ計算の自動化→一番作りたい部分
以下大言壮語。
・相手のポケモン毎に残りHPを記録しておいて見られるようにする(後攻とんぼ返りされると無理、死。)
・相手のポケモンの情報をHOMEとかから取ってきて情報をツール上で見られるようにする(出来そうで出来ない)
・OCRによる対戦ログの取得(そもそもOCRがまともに機能しないので詰み)
・対戦ログと相手のHP残量のデータと最新値からスリップダメージを除いた与ダメの計算(前提が崩壊してるのに出来るわけがない)
・与ダメから相手の型の自動判別、推定(
気長に頑張ります
tkinterのtextで最後の1行だけ削除する
たかぎです。
tkinterでツール制作をしていたのですが、テキストボックスの操作で思いの外つまずいたので備忘録として残しておきます。ボタンに紐づけたイベントでテキストボックスの中の1行を削除したかったのですが、検索するとテキストボッコスの全削除については色々なサイトに載っているものの、最後の1行あるいは特定の1行を削除しようとするとこれが欲しい情報にたどり着けず難儀しました。
- object.delete('1.0','end -1c')
全体削除はこんな感じですね。どこにでも載ってます。1行削除についても簡単なインデックス指定の方法があるかと思いきや色々な日本語のブログを探しても方法が載っていません。なので自分でまとめることにしました。結論から言うと改行の数もしくはカーソルのインデックス情報から現在の行数を計算して特定行を削除する若干回りくどい方法です。
まずは現在の行数を計算する方法から。これは簡単で
す。
- texts = object.get('1.0','end -1c')
- count_lines = texts.count('\n')+1
get()を使ってテキストボックスオブジェクトの文字列を取得して改行コード\nが何個あるかを数えます。改行が1個なら全体では2行のテキストのはずです。
- object.delete(f'{count_lines}.0', f'{count_lines}.end')
そのうえで最終行0文字目から最終行の終わりまでを削除すれば、最後の1行のみ削除出来ます。ただ、これだとその行に文字列が無い場合は何も起こりません。
例えば上の写真のような状態の場合、たちつてとの次の行にカーソルがありますが1行削除しようと思ったら消したいのは「たちつてと」の行になるのが普通だと思います。この場合はカーソル位置で分岐させる事で解決しました。
- pos = object.index('insert')
indexメソッドの引数にinsertを渡してカーソル位置を取得(textのメソッドについては調べてみてください)するとx.yの形で座標がstrで返ってくるのでカーソルが行の先頭にある場合つまりx.0の場合には一つ前の行全体を削除するようにしました。全体としてはこんな感じです。特定行の削除についても同じ要領になると思います。
- pos = object.index('insert')
- text = object.get('1.0', 'end -1c')
- count_lines = text.count('\n')+1
- if '.0' in pos:
- object.delete(f'{int(count_lines)-1}.0', f'{count_lines}.0')
- else:
- object.delete(f'{count_lines}.0', f'{count_lines}.end')
やっていること自体は非常に初歩的で簡単なのでわざわざ紹介するまでもないのですが、問題は「簡単でシンプルな方法が無いという情報がどこにもない」ことでした。無いもんは無いってはっきり言ってくれればどうにでも出来るのですが、自分の探し方が悪いせいかと思って無駄な時間を使いました…
もしこの記事が同じところで困っている誰かの役に立てば幸いです。
日記 HP残量表示ツールと自動ID厳選
こんばんは。たかぎです。
今日はPythonで遊ぼう企画の続きでHP残量表示ツールの機能追加をしていました。
具体的には過去ターンのログの表示と余計な認識を減らす改良をしてみました。一応HPバーを読み取るだけのツールとして最低限必要な機能は揃ったと思います。まあいつも感覚でランクマしてるので使うことはないんですが……。解像度の都合上でどうしても~0.5%くらいの誤差は出ますがこれもどうしようも無いので諦めです。(画像の相手がステロ踏んだ状態なので本来は87.5%のはず。)Switchが4k出力に対応したらもっと精度はあげられますがまあ無いでしょう。勉強がてら遊びで作ったもので一般公開の予定はありませんがどうしても欲しい方が居ればこっそり教えてください。
ちょっと話は変わるんですが、ランクマ真面目に潜ってるとこの場面ではステロ+攻撃で落ちるとかこの攻撃の組み合わせは耐えるとか細かいことが大事になってくるので、強くなりたかったらダメージ計算大事ですよね。しみじみ思います。面倒でサボっちゃいがちなんですケド。ランクマは現在3000位くらいで自身初の20越え目指して潜ってましたが構築が環境に微妙に刺さらなくなっている感覚があって勝ち越し数を削ってしまっています。終盤の環境変化すごい。構築を改良して試したいんですが新しい構築でいきなり潜るのもなんか怖くて、こういう時にサブロムがあったらいいんだなーと思います。今使ってるサブロムが中国語でランクバトルやりにくいので別のアカウント作り直していて、好意で頂いたポケコンの自動化プログラムでなんかかっこいいID出ないかなと頑張って(パソコンが)いますが今のところは成果ナシです。それが終わり次第ランクマやれるところまで勧めてサブロムとして使っていきたいなと思いますがいつになるやら。今後はスクレイピングの勉強とTesseractOCRの精度改善をやれればやりたいなと思いますまる。
お礼と日記
たかぎです。先日のオフレポはたくさんの方に見ていただいてありがとうございました。リツイートもたくさん頂けて嬉しい限りです。見てもらえるのって気持ちイイとちょっと危ないアレになっています。そんなこんなで今日はただの日記です。
対戦のログ取り、自動ダメージ計算、型判別etc.が出来るツールを作るべく、そして単純にPythonが面白いので勉強してみているのですが、一向に進む気配はありません。
色々弄りながらスライムを一匹ずつ倒してレベル上げしてるような感覚です。今日はまたtkinterの基本的な使い方をごにょごにょしてたのとpyinstallerに初めて触ってみてました。肝心のツールはまだHPの読み込みだけ。後はキャプチャデバイスを選択出来るようにしたりウィジェットの配置の仕方で遊んで見たりなんやかんや。
とりあえず進捗↓
行動選択画面で残りHP読むのはめちゃ簡単なんですが、実用性のある感じにしようとするとログから何のダメージが入っるか読み取って計算すると技自体のダメージは何%でってやらなきゃなくてへんてこフォント+専門用語の読み取りの壁が高すぎる。誰かOCRの学習データ下さい…🙃🙃 pic.twitter.com/WAgXVt9EQn
— TKG (@takasan1005) 2023年2月21日
OCRを使ったログの読み込みができれば一気に色々できそうなんですが、以前も書いたとおりニタラゴベースの変なフォントと一般辞書には入ってない特殊な用語の組み合わせで全く精度が出ません。今のところなんの希望もありませんが初学者はやれば伸びるため(?)とりあえず挫けずにがんばります。