ddt-sharp-shoote
这是一个基于 Pynput 的 DDT 工具。基本原理在于,得知风力、角度、距离的情况下,参考力度表得出发射力度,而后发射。 其中,风力、角度通过 ddddocr(An awesome captcha recognition library)识别,屏距通过标记屏距测量框、敌我位置来推算,力度通过按压时长来体现,具体见这里。
使用到的库:
screeninfo、pillow、ddddocr、pynput
pynput: 控制和监视输入设备;类似的有PyHook3(监视键鼠)、pywin32 (模拟键鼠)
ddddocr:识别验证码,这边用来识别数字
py2app: 将Python程序打包成MacOS应用程序
新东西:
1.进程间通信
Tkinter界面开启mainloop进程,其中又开辟出一个子线程来侦听其他进程发送的数据消息,然后通过
tk.Text
控件来展示
<pre class="md-fences md-end-block ty-contain-cm modeLoaded" spellcheck="false" lang="python" cid="n17" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Monaco, Consolas, "Andale Mono", "DejaVu Sans Mono", monospace; margin-top: 0px; margin-bottom: 20px; font-size: 0.9rem; display: block; break-inside: avoid; text-align: left; white-space: normal; background: rgb(51, 51, 51); position: relative !important; padding: 10px 10px 10px 30px; width: inherit; color: rgb(184, 191, 198); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;">import multiprocessing
import threading
import time
import tkinter
声明全局对象及类型
_tk: tkinter.Tk
_text: tkinter.Text
_terminate = False
_queue: multiprocessing.Queue
def update_text():
"""子线程侦听进程消息"""
while not _terminate:
if not _queue.empty():
text = _queue.get(False)
append_text(text)
else:
time.sleep(1)
def append_text(text):
_text.config(state='normal')
_text.insert('end', f'\n{text}')
_text.see('end')
_text.config(state='disabled')
def run(gui_queue):
global _tk, _text, _queue, _screen_size
_queue = gui_queue
...
threading.Thread(target=update_text).start()
_tk.mainloop()
</pre>
2.创建MacOS应用
py2app setup
,在macos下创建python应用, python setup.py py2app
3.识别数字并清晰
对纯数字识别结果进行清洗
<pre class="md-fences md-end-block ty-contain-cm modeLoaded" spellcheck="false" lang="python" cid="n22" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Monaco, Consolas, "Andale Mono", "DejaVu Sans Mono", monospace; margin-top: 0px; margin-bottom: 20px; font-size: 0.9rem; display: block; break-inside: avoid; text-align: left; white-space: normal; background: rgb(51, 51, 51); position: relative !important; padding: 10px 10px 10px 30px; width: inherit; color: rgb(184, 191, 198); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;">def recognize_digits(image: bytes):
ocr = ddddocr.DdddOcr(show_ad=False)
result = ocr.classification(image)
return wash_digits(result)
def wash_digits(digits: str):
"""由于不会出现非数字, 所以对易识别错误的字符进行替换"""
washed = digits
.replace('g', '9').replace('q', '9')
.replace('l', '1').replace('i', '1')
.replace('z', '2')
.replace('o', '0')
return re.sub(r'\D', '0', washed)</pre>