Python3 实现QQ游戏连连看游戏辅助
- 连连看(零)—— 前记
- 连连看(一)—— 你看,这是截图啊
- 连连看(二)—— 哦吼,PIL + CV2 + Numpy 假图像识别构建矩阵
- 连连看(三)—— 拐了拐了啊,卖拐啦(连线规则)
- 连连看(四)—— 你看我这鼠标比用户还真(Pymouse 的替身)
- 连连看(五)—— 后记 + 成果展示
本文目录
1、获取游戏整体窗口
截图使用 PIL 里的 ImageGrab,辅助使用win32gui 包,语句 win32gui.FindWindow(None,"Window's name"),返回值为一个窗口句柄(hwnd),结合win32gui.GetWindowRect(hwnd) 返回的元组,得到游戏整体窗口的位置。
# 获取游戏窗口位置(窗口不可以最小化)
def find_window() -> tuple:
hwnd = win32gui.FindWindow(None, "QQ游戏 - 连连看角色版")
left, top, right, bottom = win32gui.GetWindowRect(hwnd)
# print(left, top, right, bottom)
# 获得一个800 * 600的窗口
return left, top, right, bottom
# 使用ImageGrab截图,范围为find_window返回的元组
im = ImageGrab.grab(bbox=find_window())
这里需要注意的是,由于Windows10屏幕是自动缩放为150%的,所以程序测试和实际使用时,请将缩放调整为100%。
缩放调整方法在这里只简略说明一下:
当然,也有不调整的解决方案,将返回值全部乘1.5,但会遇到屏幕截图比预期要大,原因:存在小数点。那么使用 round() 函数来进行四舍五入是一个不错的方法。但值得注意的是,这样一来后面的所有有关于像素计算的地方都需要相应乘1.5和四舍五入,因此导致四舍五入十多个小数之后造成整数量级的偏差。
(3,3,3,3,x)----(4.5,4.5,4.5,4.5,y)
[Hint]下一个坐标 x 和 y 由于四舍五入导致相差了整整 2 个像素
[Hint]误差达到超过百分之五十,因此不建议使用。
本文使用的方法是将缩放调整为100%,效果如下:
2、获取游戏主题窗口
用尺子量结合用眼睛看得到一组重要数据:
【误!】你需要一个 PS 或一个会使用 PS 的朋友,或者,请点个赞,测量好的数据拿去。
数据都有了,我们可以操刀了(PS:方块每行19个,共11行):
# 其实这一步骤截取和保存的图片主要是为了后期矩阵计算和连线规则调试的检查使用
# 真正的图片分解没有使用到本次截图,不想要的朋友可以不保存甚至跳过此步骤截图
# 简单的数学计算进行主窗体的截取
game_window = ImageGrab.grab(bbox=(l + 14, t + 180, l + 14 + 19 * 31, t + 180 + 11 * 35))
# 保存图片
game_window.save("game_window.png")
效果如下:
3、获取切割图片
根据我们的思路(详见连连看(零)—— 前记文末),接下来就是图片切割了,把每一个小方块单独截取,转换成矩阵用来进行计算。
当然是使用 for 循环结合简单的数学计算进行截取,不多说,上代码:
# 图片切割
num = 1
print("[step1]: Cutting and saving images...")
# 高度范围中的t为第一步 l, t, r, b = find_window()
for row in range(t + 180, t + 180 + 11 * 35, 35):
for col in range(l + 14, l + 14 + 19 * 31, 31):
pic = ImageGrab.grab(bbox=(col, row, col + 31, row + 35))
pic.save("pic%s.png" % num)
num += 1
print("[step1]: Cutting and saving images finished.")
做到这里,所有的小方块(总共19 * 11 = 209块)我们都拿到手了,打开看一下,你们也会有很强的成就感吧!
坚持下去就会成功的!
【本篇完】
【附:整体代码】
# 获取游戏窗口位置(窗口不可以最小化)
def find_window() -> tuple:
hwnd = win32gui.FindWindow(None, "QQ游戏 - 连连看角色版")
left, top, right, bottom = win32gui.GetWindowRect(hwnd)
# print(left, top, right, bottom)
# 获得一个800 * 600的窗口
# Windows10 有1.5倍的屏幕缩放
# 解决方案一:将缩放从150%调为100%
# 解决方案二:将返回值全部 *1.5 但会遇到屏幕截图比预期要大 原因:存在小数点
# 屏幕截图比预期大解决方案:使用round函数 原因:获取的窗口永远没有小数点,猜测使用了round函数同理的计算方法
return left, top, right, bottom
# return round(left * 1.5), round(top * 1.5), round(right * 1.5), round(bottom * 1.5)
# 截图操作
def cut_img():
# 定位游戏整体窗口
# bbox(x-start, y-start, x-end, y-end)
l, t, r, b = find_window()
im = ImageGrab.grab(bbox=find_window())
# im.show()
# im.save("window.png")
# 定位游戏主窗口
# 主窗口:top + 180, left + 14
# 小方块:(31) * (35)
game_window = ImageGrab.grab(bbox=(l + 14, t + 180, l + 14 + 19 * 31, t + 180 + 11 * 35))
game_window.save("game_window.png")
# game_window.show()
# 图片切割
num = 1
print("[step1]: Cutting and saving images...")
for row in range(t + 180, t + 180 + 11 * 35, 35):
for col in range(l + 14, l + 14 + 19 * 31, 31):
pic = ImageGrab.grab(bbox=(col, row, col + 31, row + 35))
pic.save("pic%s.png" % num)
num += 1
print("[step1]: Cutting and saving images finished.")
【本篇完】
【下一篇:连连看(二)—— 哦吼,PIL + CV2 + Numpy 假图像识别构建矩阵】