python3小项目2-基于autopy的游戏脚本
说明:
这里笔者用的PC端的安卓模拟器为雷电模拟器,因为发现这个兼容性好
这里笔者在雷电模拟器上安装了一款心动女友app游戏
本次项目的目的:
创建一个通用库。暂时实现功能为自动打开雷电模拟器,并且自动实现心动女友游戏的恋爱功能
本次项目的原理:
用autopy的模拟鼠标点击,模拟鼠标长按,移动拖住鼠标等操作,实现自动玩游戏。并通过time的sleep函数控制时间
源码如下。本源码定义了多个类,理论可以很好的适用于其他游戏的简易自动化操作
#!/usr/bin/env python3
# _*_ coding: utf-8 _*_
# File : gamehelper.py
# Author: DaShenHan&道长-----先苦后甜,任凭晚风拂柳颜------
# Date : 2019/3/22
import win32gui, win32con,win32api
import re, traceback
from time import sleep
import autopy
from win32gui import *
class cWindow:
def __init__(self):
self._hwnd = None
def SetAsForegroundWindow(self):
# First, make sure all (other) always-on-top windows are hidden.
self.hide_always_on_top_windows()
win32gui.SetForegroundWindow(self._hwnd)
def Maximize(self):
win32gui.ShowWindow(self._hwnd, win32con.SW_MAXIMIZE)
def _window_enum_callback(self, hwnd, regex):
'''Pass to win32gui.EnumWindows() to check all open windows'''
if self._hwnd is None and re.match(regex, str(win32gui.GetWindowText(hwnd))) is not None:
self._hwnd = hwnd
def find_window_regex(self, regex):
self._hwnd = None
win32gui.EnumWindows(self._window_enum_callback, regex)
return self._hwnd
def hide_always_on_top_windows(self):
win32gui.EnumWindows(self._window_enum_callback_hide, None)
def _window_enum_callback_hide(self, hwnd, unused):
if hwnd != self._hwnd: # ignore self
# Is the window visible and marked as an always-on-top (topmost) window?
if win32gui.IsWindowVisible(hwnd) and win32gui.GetWindowLong(hwnd, win32con.GWL_EXSTYLE) & win32con.WS_EX_TOPMOST:
# Ignore windows of class 'Button' (the Start button overlay) and
# 'Shell_TrayWnd' (the Task Bar).
className = win32gui.GetClassName(hwnd)
if not (className == 'Button' or className == 'Shell_TrayWnd'):
# Force-minimize the window.
# Fortunately, this seems to work even with windows that
# have no Minimize button.
# Note that if we tried to hide the window with SW_HIDE,
# it would disappear from the Task Bar as well.
win32gui.ShowWindow(hwnd, win32con.SW_FORCEMINIMIZE)
def getallwindows(self):
"""
本方法实现获取当前所有进程列表并打印
:return: type:list() 返回当前所有进程列表
"""
titles=set()
def foo(hwnd, mouse):
if IsWindow(hwnd) and IsWindowEnabled(hwnd) and IsWindowVisible(hwnd):
titles.add(GetWindowText(hwnd))
EnumWindows(foo, 0)
list = []
for title in titles:
if title:
list.append(title)
print(list)
return list
def openapp(self,appname):
"""
本方法实现打开一个包含指定名字的窗口
:param appname: type: str('可以不是全名') 进程模糊名字
:return: 返回窗口句柄
"""
try:
regex = ".*{}.*".format(appname)
self.find_window_regex(regex)
self.Maximize()
self.SetAsForegroundWindow()
except:
f = open("log.txt", "w")
f.write(traceback.format_exc())
print(traceback.format_exc())
return self.find_window_regex(regex)
class Mouse:
def move(self, x, y,size=1):
"""
本方法实现鼠标移动到指定的坐标
:param x: type:float(0~设备最大分辨率的宽) 待移动到的x坐标
:param y: type:float(0~设备最大分辨率的高) 待移动到的y坐标
:param size: type:float(0~1) 整体应用大小设置 win10下默认应用程序是125%大小,所以这里缩放后得到0.8.默认不缩放
:return: 无返回值
"""
autopy.mouse.move(x*size, y*size)
def click(self,mode=0):
"""
本方法实现鼠标在当前位置单次点击
:param mode: type:int(0,1,2) 鼠标点击模式 0表示用左键 1表示用中键 2表示用右键 默认用鼠标左键点击
:return: 无返回值
"""
if mode == 1:
autopy.mouse.click(autopy.mouse.Button.MIDDLE)
elif mode == 2:
autopy.mouse.click(autopy.mouse.Button.RIGHT)
else:
autopy.mouse.click(autopy.mouse.Button.LEFT)
def move_click(self, x, y,size=1,mode=0):
"""
本方法实现鼠标瞬间移动到指定绝对坐标并且单次点击某个键
:param x: type:float(0~设备最大分辨率的宽) 待移动到的x坐标
:param y: type:float(0~设备最大分辨率的高) 待移动到的y坐标
:param size: type:float(0~1) 整体应用大小设置 win10下默认应用程序是125%大小,所以这里缩放后得到0.8.默认不缩放
:param mode: type:int(0,1,2) 鼠标点击模式 0表示用左键 1表示用中键 2表示用右键 默认用鼠标左键点击
:return:
"""
self.move(x*size, y*size)
self.click(mode)
def hold(self,mode=0,down=True):
"""
本方法实现长按鼠标的键与放开常按
:param mode: type:int(0,1,2) 鼠标点击模式 0表示用左键 1表示用中键 2表示用右键 默认用鼠标左键点击
:param down: type:bool(True,False) 是否按下,默认是按下。松开请用False
:return: 无返回值
"""
if mode == 1:
autopy.mouse.toggle(autopy.mouse.Button.MIDDLE,down)
elif mode == 2:
autopy.mouse.toggle(autopy.mouse.Button.RIGHT,down)
else:
autopy.mouse.toggle(autopy.mouse.Button.LEFT,down)
def location(self):
return autopy.mouse.location()
class Key:
key_zm = {chr(i): i for i in range(65, 91)}
key_num = {chr(i): i for i in range(48, 58)}
key_F = {'F%d' % (i - 111): i for i in range(112, 124)}
key_ts = {
'Backspace': 8,
'Tab': 9,
'Clear': 12,
'Enter': 13,
'Shift': 16,
'Ctrl': 17,
'Alt': 18,
'Caps Lock': 20,
'Esc': 27,
'Spacebar': 32,
'Page Up': 33,
'Page Down': 34,
'End': 35,
'Home': 36,
'Left Arrow': 37,
'Up Arrow': 38,
'Right Arrow': 39,
'Down Arrow': 40,
'Insert': 45,
'Delete': 46,
'Help': 47,
'Num Lock': 144,
'+': 107,
'-': 109,
'*': 106,
'/': 111,
'.': 110}
keycode = dict(key_zm, **key_num, **key_F, **key_ts)
def push(self, key, mode=True):
"""
:param key: type:str 按键名称 如Tab
:param mode: type:bool 按键操作 False松开 True按下 默认是按下
"""
if mode:
win32api.keybd_event(self.keycode[key], 0, 0, 0)
else:
win32api.keybd_event( self.keycode[key], 0, win32con.KEYEVENTF_KEYUP, 0)
def input(self,string,wpm=None):
autopy.key.type_string(string,wpm=wpm)
def getcode(self, key):
return self.keycode[key]
class Screen:
def getcolor(self,x,y):
return autopy.screen.get_color(x,y)
def fenbianlv(self):
width, height = autopy.screen.size()
return (width,height)
class Message:
def alert(self,info):
autopy.alert.alert(info,title='提示框')
def confirm(self,info):
a=autopy.alert.alert(info, '选择框', default_button='确定', cancel_button='取消')
return a
class XinDong:
love={'遛狗':1,'运动':2,'看电影':3,'唱歌':4,'游乐园':5,'风景区':6,'国内游':7,'境外游':8}
def qd(self):
m.move_click(823,126,0.8)
sleep(2)
m.move_click(959, 822, 0.8)
sleep(1)
m.move_click(1487, 283, 0.8)
def lianai_open(self):
m.move_click(848, 928, 0.8)
sleep(4)
m.move_click(1471, 298, 0.8)
sleep(1)
def lianai_close(self):
m.move_click(1728, 124, 0.8)
def lianai_start(self):
m.move(911, 265, 0.8)
m.hold()
m.move(1429, 262, 0.8)
m.hold(down=False)
sleep(0.5)
def lianai_do(self,thing):
thingnum=self.love[thing]
self.lianai_start()
for i in range(thingnum):
m.move(1429, 262, 0.8)
m.hold()
sleep(0.5)
m.move(911, 265, 0.8)
m.hold(down=False)
sleep(0.5)
m.move_click(825,925,0.8)
if thingnum>1:
sleep(3)
m.move_click(1146, 716, 0.8)
sleep(2)
m.move_click(825,925,0.8)
sleep(27)
m.move_click(960, 707, 0.8)
sleep(3)
def work(self):
m.move_click(1078,922,0.8)
sleep(3)
m.move_click(1471, 298, 0.8, 0)
sleep(0.5)
def where_is_the_rubbish():
'''查找回收站在屏幕中的位置'''
m.move_click(1772,16,0.8)
sleep(2)
rubbish=autopy.bitmap.Bitmap.open('resave.png')
print(rubbish)
screen=autopy.bitmap.capture_screen()
screen.save('jietu.png')
print(screen)
pos=screen.find_bitmap(rubbish)
if pos:
print ('找到了,他的位置在:%s' % str(pos))
else:
print ('没有找到')
if __name__ == '__main__':
cW = cWindow()
m = Mouse()
k = Key()
s= Screen()
ms=Message()
cW.getallwindows()
if ms.confirm('是否开始自动游戏?'):
jubing=cW.openapp('雷电模拟器')
print('应用程序窗口句柄为%s' % jubing)
sleep(2)
wg = XinDong()
wg.lianai_open()
wg.lianai_do('唱歌')
wg.lianai_close()
else:
print('pass')