def __init__(self, name='', emyc=0, hwnd=0): ''' 初始化 :param name='': 打手名称 : param emyc=0: 点怪设置:0-不点怪 : param hwnd=0: 指定窗口句柄:0-否;其他-窗口句柄 ''' # 初始参数 self.emyc = emyc self.name = name self.run = True # 读取配置文件 conf = configparser.ConfigParser() conf.read('conf.ini') quit_game_enable = conf.getboolean('watchdog', 'watchdog_enable') self.max_op_time = conf.getint('watchdog', 'max_op_time') self.max_win_time = conf.getint('watchdog', 'max_win_time') # 启动日志 self.log = WriteLog() # 绑定窗口 if hwnd == 0: hwnd = win32gui.FindWindow(0, u'阴阳师-网易游戏') self.yys = GameControl(hwnd, quit_game_enable) self.log.writeinfo(self.name + '绑定窗口成功') self.log.writeinfo(self.name + str(hwnd)) # 激活窗口 self.yys.activate_window() self.log.writeinfo(self.name + '激活窗口成功') time.sleep(0.5)
def __init__(self, name='', emyc=0, hwnd=0): ''' 初始化 :param name='': 打手名称 : param emyc=0: 点怪设置:0-不点怪 : param hwnd=0: 指定窗口句柄:0-否;其他-窗口句柄 ''' # 初始参数 self.emyc = emyc self.name = name self.run = True # 读取配置文件 conf = configparser.ConfigParser() conf.read('conf.ini') self.client = conf.getint('DEFAULT', 'client') quit_game_enable = conf.getboolean('watchdog', 'watchdog_enable') self.max_op_time = conf.getint('watchdog', 'max_op_time') self.max_win_time = conf.getint('watchdog', 'max_win_time') self.mitama_team_mark = conf.getint('mitama', 'mitama_team_mark') self.max_times = conf.getint('DEFAULT', 'max_times') self.end_operation = conf.getint('DEFAULT', 'end_operation') self.run_times = 0 # 启动日志 self.log = WriteLog() # 绑定窗口 if hwnd == 0: if self.client == 0: hwnd = win32gui.FindWindow(0, u'阴阳师-网易游戏') elif self.client == 1: hwnd = win32gui.FindWindow(0, u'阴阳师 - MuMu模拟器') # TansuoPos.InitPosWithClient__() # YuhunPos.InitPosWithClient__() self.yys = GameControl(hwnd, quit_game_enable) self.log.writeinfo(self.name + '绑定窗口成功') self.log.writeinfo(self.name + str(hwnd)) # 激活窗口 self.yys.activate_window() self.log.writeinfo(self.name + '激活窗口成功') time.sleep(0.5) # 绑定场景 # 自检 debug_enable = conf.getboolean('others', 'debug_enable') if debug_enable: task = threading.Thread(target=self.yys.debug) task.start()
class Fighter: def __init__(self, name='', emyc=0): # 初始参数 self.emyc = emyc self.name = name # 启动日志 self.log = WriteLog() # 绑定窗口 self.yys = GameControl(u'阴阳师-网易游戏') self.log.writeinfo(self.name + 'Registration successful') # 激活窗口 self.yys.activate_window() self.log.writeinfo(self.name + 'Activation successful') ut.mysleep(500) def check_battle(self): # 检测是否进入战斗 self.yys.wait_game_img('img\\ZI-DONG.png') self.log.writeinfo(self.name + 'Already in battle') def check_end(self): # 检测是否打完 self.yys.wait_game_img('img\\JIE-SU.png') self.log.writeinfo(self.name + "Battle finished") def click_monster(self): # 点击怪物 pass
def __init__(self, hwnd, quit_game_enable=1): ''' 初始化 :param hwnd: 需要绑定的窗口句柄 :param quit_game_enable: 程序死掉时是否退出游戏。True为是,False为否 ''' self.run = True self.hwnd = hwnd self.quit_game_enable = quit_game_enable #user32 = ctypes.windll.user32 #user32.SetProcessDPIAware() # 启动日志 self.log = WriteLog()
def __init__(self, name='', emyc=0): # 初始参数 self.emyc = emyc self.name = name # 启动日志 self.log = WriteLog() # 绑定窗口 self.yys = GameControl(u'阴阳师-网易游戏') self.log.writeinfo(self.name + 'Registration successful') # 激活窗口 self.yys.activate_window() self.log.writeinfo(self.name + 'Activation successful') ut.mysleep(500)
def __init__(self, name='', emyc=0, hwnd=0): ''' 初始化 :param name='': 打手名称 : param emyc=0: 点怪设置:0-不点怪 : param hwnd=0: 指定窗口句柄:0-否;其他-窗口句柄 ''' # 初始参数 self.emyc = emyc self.name = name self.run = True self.run_time = time.time() # 读取配置文件 conf = configparser.ConfigParser() conf.read('conf.ini') quit_game_enable = conf.getboolean('watchdog', 'watchdog_enable') self.max_op_time = conf.getint('watchdog', 'max_op_time') self.max_win_time = conf.getint('watchdog', 'max_win_time') self.quit_time = conf.getint('watchdog', 'quit_time') self.team = conf.getboolean('others', 'team') self.team_id = conf.getint('others', 'team_id') self.monster = conf.getboolean('others', 'monster') # 启动日志 self.log = WriteLog() # 绑定窗口 if hwnd == 0: hwnd = win32gui.FindWindow(0, u'阴阳师-网易游戏') self.yys = GameControl(hwnd, quit_game_enable) self.log.writeinfo(self.name + '绑定窗口成功') self.log.writeinfo(self.name + str(hwnd)) # 激活窗口 self.yys.activate_window() self.log.writeinfo(self.name + '激活窗口成功') time.sleep(0.5) # 自检 debug_enable = conf.getboolean('others', 'debug_enable') if debug_enable: task = threading.Thread(target=self.yys.debug) task.start()
def __init__(self, name='', emyc=0): # 初始参数 self.emyc = emyc self.name = name # 读取配置文件 conf = configparser.ConfigParser() conf.read('conf.ini') quit_game_enable = conf.getboolean('watchdog', 'watchdog_enable') self.max_op_time = conf.getint('watchdog', 'max_op_time') self.max_win_time = conf.getint('watchdog', 'max_win_time') # 启动日志 self.log = WriteLog() # 绑定窗口 self.yys = GameControl(u'阴阳师-网易游戏', quit_game_enable) self.log.writeinfo(self.name + 'Registration successful') # 激活窗口 self.yys.activate_window() self.log.writeinfo(self.name + 'Activation successful') time.sleep(0.5)
def __init__(self, name='', emyc=0, hwnd=0, activate=True): ''' 初始化 :param name='': 打手名称 : param emyc=0: 点怪设置:0-不点怪 : param hwnd=0: 指定窗口句柄:0-否;其他-窗口句柄 : param activate=True: 是否激活窗口,支线任务不需要激活 ''' # 初始参数 self.emyc = emyc self.name = name self.run = True # 读取配置文件 conf = configparser.ConfigParser() conf.read('conf.ini') quit_game_enable = conf.getboolean('watchdog', 'watchdog_enable') self.max_op_time = conf.getint('watchdog', 'max_op_time') self.max_win_time = conf.getint('watchdog', 'max_win_time') # 启动日志 self.log = WriteLog() # 绑定窗口 if hwnd == 0: hwnd = win32gui.FindWindow('Win32Window0', u'阴阳师-网易游戏') # hwnd = win32gui.FindWindow('Qt5QWindowIcon', '夜神模拟器') # hwnd = win32gui.FindWindowEx(hwnd, 0, 'Qt5QWindowIcon', 'ScreenBoardClassWindow') self.yys = GameControl(hwnd, quit_game_enable) self.log.writeinfo(self.name + '绑定窗口成功') self.log.writeinfo(self.name + str(hwnd)) if activate: # 激活窗口 self.yys.activate_window() self.log.writeinfo(self.name + '激活窗口成功') time.sleep(0.5)
class Fighter: def __init__(self, name='', emyc=0, hwnd=0): ''' 初始化 :param name='': 打手名称 : param emyc=0: 点怪设置:0-不点怪 : param hwnd=0: 指定窗口句柄:0-否;其他-窗口句柄 ''' # 初始参数 self.emyc = emyc self.name = name self.run = True # 读取配置文件 conf = configparser.ConfigParser() conf.read('conf.ini') quit_game_enable = conf.getboolean('watchdog', 'watchdog_enable') self.max_op_time = conf.getint('watchdog', 'max_op_time') self.max_win_time = conf.getint('watchdog', 'max_win_time') # 启动日志 self.log = WriteLog() # 绑定窗口 if hwnd == 0: hwnd = win32gui.FindWindow(0, u'阴阳师-网易游戏') self.yys = GameControl(hwnd, quit_game_enable) self.log.writeinfo(self.name + '绑定窗口成功') self.log.writeinfo(self.name + str(hwnd)) # 激活窗口 self.yys.activate_window() self.log.writeinfo(self.name + '激活窗口成功') time.sleep(0.5) def check_battle(self): # 检测是否进入战斗 self.log.writeinfo(self.name + '检测是否进入战斗') self.yys.wait_game_img('img\\ZI-DONG.png', self.max_win_time) self.log.writeinfo(self.name + '已进入战斗') def check_end(self): # 检测是否打完 self.log.writeinfo(self.name + '检测是战斗是否结束') self.yys.wait_game_img('img\\JIE-SU.png', self.max_win_time) self.log.writeinfo(self.name + "战斗结束") def click_monster(self): # 点击怪物 pass def click_until(self, tag, img_path, pos, pos_end=None, step_time=None, appear=True, point=0.97): ''' 在某一时间段内,后台点击鼠标,直到出现某一图片出现或消失 :param tag: 按键名 :param img_path: 图片路径 :param pos: (x,y) 鼠标单击的坐标 :param pos_end=None: (x,y) 若pos_end不为空,则鼠标单击以pos为左上角坐标pos_end为右下角坐标的区域内的随机位置 :step_time=0.5: 查询间隔 :appear: 图片出现或消失:Ture-出现;False-消失 :point: 判定图片的的识别概率 :return: 成功返回True, 失败退出游戏 ''' # 在指定时间内反复监测画面并点击 start_time = time.time() while time.time()-start_time <= self.max_op_time and self.run: result = self.yys.find_game_img(img_path, point=point) if not appear: result = not result if result: self.log.writeinfo(self.name + '点击 ' + tag + ' 成功') return True else: # 点击指定位置并等待下一轮 self.yys.mouse_click_bg(pos, pos_end) self.log.writeinfo(self.name + '点击 ' + tag) if step_time == None: time.sleep(random.randint(1, 3)) else: time.sleep(step_time) self.log.writewarning(self.name + '点击 ' + tag + ' 失败!') # 提醒玩家点击失败,并在5s后退出 self.yys.activate_window() time.sleep(5) # self.yys.quit_game() self.log.writewarning("强制退出脚本") sys.exit(0) def activate(self): self.log.writewarning(self.name + '启动脚本') self.run = True self.yys.run = True def deactivate(self): self.log.writewarning(self.name + '手动停止脚本') self.run = False self.yys.run = False def slide_x_scene(self, distance): ''' 水平滑动场景 :return: 成功返回True; 失败返回False ''' x0 = random.randint(distance + 10, 1126) x1 = x0 - distance y0 = random.randint(436, 486) y1 = random.randint(436, 486) self.yys.mouse_drag_bg((x0, y0), (x1, y1)) logging.info(self.name + '水平滑动界面') def get_scene(self): ''' 识别当前场景 :return: 返回场景名称:1-庭院; 2-探索界面; 3-章节界面; 4-探索内 ''' # 拒绝悬赏 self.yys.rejectbounty() # 分别识别庭院、探索、章节页、探索内 maxVal, maxLoc = self.yys.find_multi_img( 'img\\JIA-CHENG.png', 'img\\JUE-XING.png', 'img\\TAN-SUO.png', 'img\\YING-BING.png') scene_cof = max(maxVal) if scene_cof > 0.97: scene = maxVal.index(scene_cof) return scene + 1 else: return 0 def get_scene_baigui(self): ''' 识别百鬼结束的画面 :return: 返回场景名称:1-百鬼首页,2-结算页面 ''' # 拒绝悬赏 self.yys.rejectbounty() # 分别识别百鬼首页、结算页面 maxVal, maxLoc = self.yys.find_multi_img( 'img\\BAI-GUI-YE-XING.png', 'img\\BAI-GUI-QI-YUE-SHU.png') scene_cof = max(maxVal) if scene_cof > 0.97: scene = maxVal.index(scene_cof) return scene + 1 else: return 0 def get_scene_breakthrough(self): ''' 识别结界突破结果 :return: 返回场景名称:1-成功,2-失败 ''' # 拒绝悬赏 self.yys.rejectbounty() # 分别识别百鬼首页、结算页面 maxVal, maxLoc = self.yys.find_multi_img( 'img\\SHENG-LI.png', 'img\\SHI-BAI.png') scene_cof = max(maxVal) if scene_cof > 0.97: scene = maxVal.index(scene_cof) return scene + 1 else: return 0 def switch_to_scene(self, scene): ''' 切换场景 :param scene: 需要切换到的场景:1-庭院; 2-探索界面; 3-章节界面; 4-探索内 :return: 切换成功返回True;切换失败直接退出 ''' scene_now = self.get_scene() logging.info(self.name + '目前场景:' + str(scene_now)) if scene_now == scene: return True if scene_now == 1: # 庭院中 if scene == 2 or scene == 3 or scene == 4: # 先将界面划到最右边 self.slide_x_scene(800) time.sleep(2) self.slide_x_scene(800) # 点击探索灯笼进入探索界面 self.click_until('探索灯笼', 'img\\JUE-XING.png', * TansuoPos.tansuo_denglong) # 递归 self.switch_to_scene(scene) if scene_now == 2: # 探索界面 if scene == 3 or scene == 4: # 点击最后章节 self.click_until('最后章节', 'img\\TAN-SUO.png', *TansuoPos.last_chapter) # 递归 self.switch_to_scene(scene) if scene_now == 3: # 章节界面 if scene == 4: # 点击探索按钮 self.click_until('探索按钮', 'img\\YING-BING.png', *TansuoPos.tansuo_btn) # 递归 self.switch_to_scene(scene) if scene_now == 4: # 探索内 if scene == 3: # 点击退出探索 self.click_until('退出按钮', 'img\\QUE-REN.png', *TansuoPos.quit_btn) # 点击确认 self.click_until('确认按钮', 'img\\QUE-REN.png', *TansuoPos.confirm_btn, 2, False) # 递归 self.switch_to_scene(scene)
class Fighter: def __init__(self, name='', emyc=0, hwnd=0): ''' 初始化 :param name='': 打手名称 : param emyc=0: 点怪设置:0-不点怪 : param hwnd=0: 指定窗口句柄:0-否;其他-窗口句柄 ''' # 初始参数 self.emyc = emyc self.name = name self.run = True # 读取配置文件 conf = configparser.ConfigParser() conf.read('conf.ini') quit_game_enable = conf.getboolean('watchdog', 'watchdog_enable') self.max_op_time = conf.getint('watchdog', 'max_op_time') self.max_win_time = conf.getint('watchdog', 'max_win_time') self.mitama_team_mark = conf.getint('mitama', 'mitama_team_mark') # 启动日志 self.log = WriteLog() # 绑定窗口 if hwnd == 0: hwnd = win32gui.FindWindow(0, u'阴阳师-网易游戏') self.yys = GameControl(hwnd, quit_game_enable) self.log.writeinfo(self.name + '绑定窗口成功') self.log.writeinfo(self.name + str(hwnd)) # 激活窗口 self.yys.activate_window() self.log.writeinfo(self.name + '激活窗口成功') time.sleep(0.5) # 自检 debug_enable = conf.getboolean('others', 'debug_enable') if debug_enable: task = threading.Thread(target=self.yys.debug) task.start() def check_battle(self): # 检测是否进入战斗 self.log.writeinfo(self.name + '检测是否进入战斗') self.yys.wait_game_img('img\\ZI-DONG.png', self.max_win_time) self.log.writeinfo(self.name + '已进入战斗') def check_end(self): # 检测是否打完 self.log.writeinfo(self.name + '检测是战斗是否结束') self.yys.wait_game_img('img\\JIE-SU.png', self.max_win_time) self.log.writeinfo(self.name + "战斗结束") def mitama_team_click(self): ''' 御魂标记己方式神 ''' num = self.mitama_team_mark if num > 0: # 100 1040 # 125 50 # 御魂场景获取标记位置 min = (num - 1) * 105 + (num - 1) * 100 + 95 max = min + 50 pos = (min, 355), (max, 425) start_time = time.time() while time.time() - start_time <= 3: x1 = pos[0][0] - 100 y1 = pos[0][1] - 250 x2 = pos[1][0] + 100 y2 = pos[1][1] exp_pos = self.yys.find_color( ((x1, y1), (x2, y2)), (134, 227, 96), 5) # print('颜色位置', exp_pos) if exp_pos != -1: self.log.writeinfo(self.name + '标记式神成功') return True else: # 点击指定位置并等待下一轮 self.yys.mouse_click_bg(*pos) self.log.writeinfo(self.name + '标记式神') time.sleep(0.4) self.log.writewarning(self.name + '标记式神失败') def click_monster(self): # 点击怪物 pass def click_until(self, tag, img_path, pos, pos_end=None, step_time=0.5, appear=True): ''' 在某一时间段内,后台点击鼠标,直到出现某一图片出现或消失 :param tag: 按键名 :param img_path: 图片路径 :param pos: (x,y) 鼠标单击的坐标 :param pos_end=None: (x,y) 若pos_end不为空,则鼠标单击以pos为左上角坐标pos_end为右下角坐标的区域内的随机位置 :step_time=0.5: 查询间隔 :appear: 图片出现或消失:Ture-出现;False-消失 :return: 成功返回True, 失败退出游戏 ''' # 在指定时间内反复监测画面并点击 start_time = time.time() while time.time()-start_time <= self.max_op_time and self.run: result = self.yys.find_game_img(img_path) if not appear: result = not result if result: self.log.writeinfo(self.name + '点击 ' + tag + ' 成功') return True else: # 点击指定位置并等待下一轮 self.yys.mouse_click_bg(pos, pos_end) self.log.writeinfo(self.name + '点击 ' + tag) time.sleep(step_time) self.log.writewarning(self.name + '点击 ' + tag + ' 失败!') # 提醒玩家点击失败,并在5s后退出 self.yys.activate_window() time.sleep(5) self.yys.quit_game() def activate(self): self.log.writewarning(self.name + '启动脚本') self.run = True self.yys.run = True def deactivate(self): self.log.writewarning(self.name + '手动停止脚本') self.run = False self.yys.run = False def slide_x_scene(self, distance): ''' 水平滑动场景 :return: 成功返回True; 失败返回False ''' x0 = random.randint(distance + 10, 1126) x1 = x0 - distance y0 = random.randint(436, 486) y1 = random.randint(436, 486) self.yys.mouse_drag_bg((x0, y0), (x1, y1)) logging.info(self.name + '水平滑动界面') def get_scene(self): ''' 识别当前场景 :return: 返回场景名称:1-庭院; 2-探索界面; 3-章节界面; 4-探索内 ''' # 拒绝悬赏 self.yys.rejectbounty() # 分别识别庭院、探索、章节页、探索内 maxVal, maxLoc = self.yys.find_multi_img( 'img/JIA-CHENG.png', 'img/JUE-XING.png', 'img/TAN-SUO.png', 'img/YING-BING.png') scene_cof = max(maxVal) if scene_cof > 0.97: scene = maxVal.index(scene_cof) return scene + 1 else: return 0 def switch_to_scene(self, scene): ''' 切换场景 :param scene: 需要切换到的场景:1-庭院; 2-探索界面; 3-章节界面; 4-探索内 :return: 切换成功返回True;切换失败直接退出 ''' scene_now = self.get_scene() logging.info(self.name + '目前场景:' + str(scene_now)) if scene_now == scene: return True if scene_now == 1: # 庭院中 if scene == 2 or scene == 3 or scene == 4: # 先将界面划到最右边 self.slide_x_scene(800) time.sleep(2) self.slide_x_scene(800) # 点击探索灯笼进入探索界面 self.click_until('探索灯笼', 'img/JUE-XING.png', * TansuoPos.tansuo_denglong, 2) # 递归 self.switch_to_scene(scene) if scene_now == 2: # 探索界面 if scene == 3 or scene == 4: # 点击最后章节 self.click_until('最后章节', 'img/TAN-SUO.png', *TansuoPos.last_chapter, 2) # 递归 self.switch_to_scene(scene) if scene_now == 3: # 章节界面 if scene == 4: # 点击探索按钮 self.click_until('探索按钮', 'img/YING-BING.png', *TansuoPos.tansuo_btn, 2) # 递归 self.switch_to_scene(scene) if scene_now == 4: # 探索内 if scene == 3: # 点击退出探索 self.click_until('退出按钮', 'img\\QUE-REN.png', *TansuoPos.quit_btn, 2) # 点击确认 self.click_until('确认按钮', 'img\\QUE-REN.png', *TansuoPos.confirm_btn, 2, False) # 递归 self.switch_to_scene(scene)
class GameControl(): def __init__(self, hwnd, quit_game_enable=1): ''' 初始化 :param hwnd: 需要绑定的窗口句柄 :param quit_game_enable: 程序死掉时是否退出游戏。True为是,False为否 ''' self.run = True self.hwnd = hwnd self.quit_game_enable = quit_game_enable #user32 = ctypes.windll.user32 #user32.SetProcessDPIAware() # 启动日志 self.log = WriteLog() def window_full_shot(self, file_name=None, gray=0): """ 窗口截图 :param file_name=None: 截图文件的保存名称 :param gray=0: 是否返回灰度图像,0:返回BGR彩色图像,其他:返回灰度黑白图像 :return: file_name为空则返回RGB数据 """ try: l, t, r, b = win32gui.GetWindowRect(self.hwnd) # 39和16为Window与Client高和宽的差值 h = b - t - 39 w = r - l - 16 hwindc = win32gui.GetWindowDC(self.hwnd) srcdc = win32ui.CreateDCFromHandle(hwindc) memdc = srcdc.CreateCompatibleDC() bmp = win32ui.CreateBitmap() bmp.CreateCompatibleBitmap(srcdc, w, h) memdc.SelectObject(bmp) memdc.BitBlt((0, 0), (w, h), srcdc, (8, 31), win32con.SRCCOPY) if file_name != None: bmp.SaveBitmapFile(memdc, file_name) srcdc.DeleteDC() memdc.DeleteDC() win32gui.ReleaseDC(self.hwnd, hwindc) win32gui.DeleteObject(bmp.GetHandle()) return else: signedIntsArray = bmp.GetBitmapBits(True) img = np.fromstring(signedIntsArray, dtype='uint8') img.shape = (h, w, 4) srcdc.DeleteDC() memdc.DeleteDC() win32gui.ReleaseDC(self.hwnd, hwindc) win32gui.DeleteObject(bmp.GetHandle()) #cv2.imshow("image", cv2.cvtColor(img, cv2.COLOR_BGRA2GRAY)) # cv2.waitKey(0) if gray == 0: return cv2.cvtColor(img, cv2.COLOR_BGRA2BGR) else: return cv2.cvtColor(img, cv2.COLOR_BGRA2GRAY) except: pass def window_part_shot(self, pos1, pos2, file_name=None, gray=0): """ 窗口区域截图 :param pos1: (x,y) 截图区域的左上角坐标 :param pos2: (x,y) 截图区域的右下角坐标 :param file_name=None: 截图文件的保存路径 :param gray=0: 是否返回灰度图像,0:返回BGR彩色图像,其他:返回灰度黑白图像 :return: file_name为空则返回RGB数据 """ w = pos2[0] - pos1[0] h = pos2[1] - pos1[1] hwindc = win32gui.GetWindowDC(self.hwnd) srcdc = win32ui.CreateDCFromHandle(hwindc) memdc = srcdc.CreateCompatibleDC() bmp = win32ui.CreateBitmap() bmp.CreateCompatibleBitmap(srcdc, w, h) memdc.SelectObject(bmp) memdc.BitBlt((0, 0), (w, h), srcdc, (pos1[0] + 8, pos1[1] + 31), win32con.SRCCOPY) if file_name != None: bmp.SaveBitmapFile(memdc, file_name) srcdc.DeleteDC() memdc.DeleteDC() win32gui.ReleaseDC(self.hwnd, hwindc) win32gui.DeleteObject(bmp.GetHandle()) return else: signedIntsArray = bmp.GetBitmapBits(True) img = np.fromstring(signedIntsArray, dtype='uint8') img.shape = (h, w, 4) srcdc.DeleteDC() memdc.DeleteDC() win32gui.ReleaseDC(self.hwnd, hwindc) win32gui.DeleteObject(bmp.GetHandle()) #cv2.imshow("image", cv2.cvtColor(img, cv2.COLOR_BGRA2BGR)) # cv2.waitKey(0) if gray == 0: return cv2.cvtColor(img, cv2.COLOR_BGRA2BGR) else: return cv2.cvtColor(img, cv2.COLOR_BGRA2GRAY) def find_color(self, region, color, tolerance=0): """ 寻找颜色 :param region: ((x1,y1),(x2,y2)) 欲搜索区域的左上角坐标和右下角坐标 :param color: (r,g,b) 欲搜索的颜色 :param tolerance=0: 容差值 :return: 成功返回客户区坐标,失败返回-1 """ img = Image.fromarray(self.window_part_shot(region[0], region[1]), 'RGB') width, height = img.size r1, g1, b1 = color[:3] for x in range(width): for y in range(height): try: pixel = img.getpixel((x, y)) r2, g2, b2 = pixel[:3] if abs(r1 - r2) <= tolerance and abs( g1 - g2) <= tolerance and abs(b1 - b2) <= tolerance: return x + region[0][0], y + region[0][1] except: return -1 return -1 def check_color(self, pos, color, tolerance=0): """ 对比窗口内某一点的颜色 :param pos: (x,y) 欲对比的坐标 :param color: (r,g,b) 欲对比的颜色 :param tolerance=0: 容差值 :return: 成功返回True,失败返回False """ img = Image.fromarray(self.window_full_shot(), 'RGB') r1, g1, b1 = color[:3] r2, g2, b2 = img.getpixel(pos)[:3] if abs(r1 - r2) <= tolerance and abs(g1 - g2) <= tolerance and abs( b1 - b2) <= tolerance: return True else: return False def find_img(self, img_template_path, part=0, pos1=None, pos2=None, gray=0): """ 查找图片 :param img_template_path: 欲查找的图片路径 :param part=0: 是否全屏查找,1为否,其他为是 :param pos1=None: 欲查找范围的左上角坐标 :param pos2=None: 欲查找范围的右下角坐标 :param gray=0: 是否彩色查找,0:查找彩色图片,1:查找黑白图片 :return: (maxVal,maxLoc) maxVal为相关性,越接近1越好,maxLoc为得到的坐标 """ # 获取截图 if part == 1: img_src = self.window_part_shot(pos1, pos2, None, gray) else: img_src = self.window_full_shot(None, gray) # show_img(img_src) # 读入文件 if gray == 0: img_template = cv2.imread(img_template_path, cv2.IMREAD_COLOR) else: img_template = cv2.imread(img_template_path, cv2.IMREAD_GRAYSCALE) try: res = cv2.matchTemplate(img_src, img_template, cv2.TM_CCOEFF_NORMED) minVal, maxVal, minLoc, maxLoc = cv2.minMaxLoc(res) # print(maxLoc) return maxVal, maxLoc except: return 0, 0 def find_multi_img(self, *img_template_path, part=0, pos1=None, pos2=None, gray=0): """ 查找多张图片 :param img_template_path: 欲查找的图片路径列表 :param part=0: 是否全屏查找,1为否,其他为是 :param pos1=None: 欲查找范围的左上角坐标 :param pos2=None: 欲查找范围的右下角坐标 :param gray=0: 是否彩色查找,0:查找彩色图片,1:查找黑白图片 :return: (maxVal,maxLoc) maxVal为相关性列表,越接近1越好,maxLoc为得到的坐标列表 """ # 窗口截图 if part == 1: img_src = self.window_part_shot(pos1, pos2, None, gray) else: img_src = self.window_full_shot(None, gray) # 返回值列表 maxVal_list = [] maxLoc_list = [] for item in img_template_path: # 读入文件 if gray == 0: img_template = cv2.imread(item, cv2.IMREAD_COLOR) else: img_template = cv2.imread(item, cv2.IMREAD_GRAYSCALE) # 开始识别 try: res = cv2.matchTemplate(img_src, img_template, cv2.TM_CCOEFF_NORMED) minVal, maxVal, minLoc, maxLoc = cv2.minMaxLoc(res) maxVal_list.append(maxVal) maxLoc_list.append(maxLoc) except: maxVal_list.append(0) maxLoc_list.append(0) # 返回列表 return maxVal_list, maxLoc_list def activate_window(self): user32 = ctypes.WinDLL('user32.dll') user32.SwitchToThisWindow(self.hwnd, True) def mouse_move(self, pos, pos_end=None): """ 模拟鼠标移动 :param pos: (x,y) 鼠标移动的坐标 :param pos_end=None: (x,y) 若pos_end不为空,则鼠标移动至以pos为左上角坐标pos_end为右下角坐标的区域内的随机位置 """ pos2 = win32gui.ClientToScreen(self.hwnd, pos) if pos_end == None: win32api.SetCursorPos(pos2) else: pos_end2 = win32gui.ClientToScreen(self.hwnd, pos_end) pos_rand = (random.randint(pos2[0], pos_end2[0]), random.randint(pos2[1], pos_end2[1])) win32api.SetCursorPos(pos_rand) def mouse_click(self): """ 鼠标单击 """ win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0) time.sleep(random.randint(20, 80) / 1000) win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP, 0, 0, 0, 0) def mouse_drag(self, pos1, pos2): """ 鼠标拖拽 :param pos1: (x,y) 起点坐标 :param pos2: (x,y) 终点坐标 """ pos1_s = win32gui.ClientToScreen(self.hwnd, pos1) pos2_s = win32gui.ClientToScreen(self.hwnd, pos2) screen_x = win32api.GetSystemMetrics(win32con.SM_CXSCREEN) screen_y = win32api.GetSystemMetrics(win32con.SM_CYSCREEN) start_x = pos1_s[0] * 65535 // screen_x start_y = pos1_s[1] * 65535 // screen_y dst_x = pos2_s[0] * 65535 // screen_x dst_y = pos2_s[1] * 65535 // screen_y move_x = np.linspace(start_x, dst_x, num=20, endpoint=True)[0:] move_y = np.linspace(start_y, dst_y, num=20, endpoint=True)[0:] self.mouse_move(pos1) win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0) for i in range(20): x = int(round(move_x[i])) y = int(round(move_y[i])) win32api.mouse_event( win32con.MOUSEEVENTF_MOVE | win32con.MOUSEEVENTF_ABSOLUTE, x, y, 0, 0) time.sleep(0.01) win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP, 0, 0, 0, 0) def mouse_click_bg(self, pos, pos_end=None): """ 后台鼠标单击 :param pos: (x,y) 鼠标单击的坐标 :param pos_end=None: (x,y) 若pos_end不为空,则鼠标单击以pos为左上角坐标pos_end为右下角坐标的区域内的随机位置 """ if pos_end == None: win32gui.SendMessage(self.hwnd, win32con.WM_MOUSEMOVE, 0, win32api.MAKELONG(pos[0], pos[1])) win32gui.SendMessage(self.hwnd, win32con.WM_LBUTTONDOWN, 0, win32api.MAKELONG(pos[0], pos[1])) time.sleep(random.randint(20, 80) / 1000) win32gui.SendMessage(self.hwnd, win32con.WM_LBUTTONUP, 0, win32api.MAKELONG(pos[0], pos[1])) else: pos_rand = (random.randint(pos[0], pos_end[0]), random.randint(pos[1], pos_end[1])) win32gui.SendMessage(self.hwnd, win32con.WM_MOUSEMOVE, 0, win32api.MAKELONG(pos_rand[0], pos_rand[1])) win32gui.SendMessage(self.hwnd, win32con.WM_LBUTTONDOWN, 0, win32api.MAKELONG(pos_rand[0], pos_rand[1])) time.sleep(random.randint(20, 80) / 1000) win32gui.SendMessage(self.hwnd, win32con.WM_LBUTTONUP, 0, win32api.MAKELONG(pos_rand[0], pos_rand[1])) def mouse_double_click_bg(self, pos, pos_end): """ 后台鼠标双击 :param pos: (x,y) 鼠标双击的坐标 :param pos_end=None: (x,y) 若pos_end不为空,则鼠标双击以pos为左上角坐标pos_end为右下角坐标的区域内的随机位置 """ # 获取随机位置 pos_rand = (random.randint(pos[0], pos_end[0]), random.randint(pos[1], pos_end[1])) for i in range(2): win32gui.SendMessage(self.hwnd, win32con.WM_MOUSEMOVE, 0, win32api.MAKELONG(pos_rand[0], pos_rand[1])) win32gui.SendMessage(self.hwnd, win32con.WM_LBUTTONDOWN, 0, win32api.MAKELONG(pos_rand[0], pos_rand[1])) time.sleep(random.randint(20, 80) / 1000) win32gui.SendMessage(self.hwnd, win32con.WM_LBUTTONUP, 0, win32api.MAKELONG(pos_rand[0], pos_rand[1])) time.sleep(random.randint(100, 200) / 1000) def mouse_drag_bg(self, pos1, pos2): """ 后台鼠标拖拽 :param pos1: (x,y) 起点坐标 :param pos2: (x,y) 终点坐标 """ move_x = np.linspace(pos1[0], pos2[0], num=20, endpoint=True)[0:] move_y = np.linspace(pos1[1], pos2[1], num=20, endpoint=True)[0:] win32gui.SendMessage(self.hwnd, win32con.WM_LBUTTONDOWN, 0, win32api.MAKELONG(pos1[0], pos1[1])) for i in range(20): x = int(round(move_x[i])) y = int(round(move_y[i])) win32gui.SendMessage(self.hwnd, win32con.WM_MOUSEMOVE, 0, win32api.MAKELONG(x, y)) time.sleep(0.01) win32gui.SendMessage(self.hwnd, win32con.WM_LBUTTONUP, 0, win32api.MAKELONG(pos2[0], pos2[1])) def wait_game_img(self, img_path, max_time=100, quit=True): """ 等待游戏图像 :param img_path: 图片路径 :param max_time=60: 超时时间 :param quit=True: 超时后是否退出 :return: 成功返回坐标,失败返回False """ self.rejectbounty() start_time = time.time() while time.time() - start_time <= max_time and self.run: maxVal, maxLoc = self.find_img(img_path) if maxVal > 0.97: return maxLoc if max_time > 5: time.sleep(1) else: time.sleep(0.1) if quit: # 超时则退出游戏 # self.quit_game() self.log.writewarning("强制退出脚本") sys.exit(0) else: return False def wait_game_img_disappear(self, img_path, max_time=100, quit=True): """ 等待游戏图像消失 :param img_path: 图片路径 :param max_time=60: 超时时间 :param quit=True: 超时后是否退出 :return: 成功返回坐标,失败返回False """ self.rejectbounty() start_time = time.time() while time.time() - start_time <= max_time and self.run: maxVal, maxLoc = self.find_img(img_path) if maxVal < 0.97: return maxLoc if max_time > 5: time.sleep(1) else: time.sleep(0.1) if quit: # 超时则退出游戏 # self.quit_game() self.log.writewarning("强制退出脚本") sys.exit(0) else: return False def wait_multi_game_img(self, *img_path, max_time=100, quit=True): """ 等待游戏图像 :param img_path: 图片路径 :param max_time=60: 超时时间 :param quit=True: 超时后是否退出 :return: 成功返回坐标,失败返回False """ self.rejectbounty() start_time = time.time() while time.time() - start_time <= max_time and self.run: for item in img_path: maxVal, maxLoc = self.find_img(item) if maxVal > 0.97: return maxLoc if max_time > 5: time.sleep(1) else: time.sleep(0.1) if quit: # 超时则退出游戏 # self.quit_game() self.log.writewarning("强制退出脚本") sys.exit(0) else: return False def wait_game_color(self, region, color, tolerance=0, max_time=60, quit=True): """ 等待游戏颜色 :param region: ((x1,y1),(x2,y2)) 欲搜索的区域 :param color: (r,g,b) 欲等待的颜色 :param tolerance=0: 容差值 :param max_time=30: 超时时间 :param quit=True: 超时后是否退出 :return: 成功返回True,失败返回False """ self.rejectbounty() start_time = time.time() while time.time() - start_time <= max_time and self.run: pos = self.find_color(region, color) if pos != -1: return True time.sleep(1) if quit: # 超时则退出游戏 # self.quit_game() self.log.writewarning("强制退出脚本") sys.exit(0) else: return False def quit_game(self): """ 退出游戏 """ self.takescreenshot() # 保存一下现场 if not self.run: return False if self.quit_game_enable: win32gui.SendMessage(self.hwnd, win32con.WM_DESTROY, 0, 0) # 退出游戏 sys.exit(0) def takescreenshot(self): ''' 截图 ''' img_src_path = 'img\\full.png' self.window_full_shot(img_src_path) def rejectbounty(self): ''' 拒绝悬赏 :return: 拒绝成功返回True,其他情况返回False ''' maxVal, maxLoc = self.find_img('img\\XUAN-SHANG.png') if maxVal > 0.97: self.mouse_click_bg((757, 460)) return True return False def find_game_img(self, img_path, part=0, pos1=None, pos2=None, gray=0, point=0.97): ''' 查找图片 :param img_path: 查找路径 :param part=0: 是否全屏查找,1为否,其他为是 :param pos1=None: 欲查找范围的左上角坐标 :param pos2=None: 欲查找范围的右下角坐标 :param gray=0: 是否查找黑白图片,0:查找彩色图片,1:查找黑白图片 :param point: 判定图片的的识别概率 :return: 查找成功返回位置坐标,否则返回False ''' self.rejectbounty() maxVal, maxLoc = self.find_img(img_path, part, pos1, pos2, gray) # print(maxVal) if maxVal > point: return maxLoc else: return False
class Fighter: def __init__(self, name='', emyc=0, hwnd=0): ''' 初始化 :param name='': 打手名称 : param emyc=0: 点怪设置:0-不点怪 : param hwnd=0: 指定窗口句柄:0-否;其他-窗口句柄 ''' # 初始参数 self.emyc = emyc self.name = name self.run = True self.run_time = time.time() # 读取配置文件 conf = configparser.ConfigParser() conf.read('conf.ini') quit_game_enable = conf.getboolean('watchdog', 'watchdog_enable') self.max_op_time = conf.getint('watchdog', 'max_op_time') self.max_win_time = conf.getint('watchdog', 'max_win_time') self.quit_time = conf.getint('watchdog', 'quit_time') self.team = conf.getboolean('others', 'team') self.team_id = conf.getint('others', 'team_id') self.monster = conf.getboolean('others', 'monster') # 启动日志 self.log = WriteLog() # 绑定窗口 if hwnd == 0: hwnd = win32gui.FindWindow(0, u'阴阳师-网易游戏') self.yys = GameControl(hwnd, quit_game_enable) self.log.writeinfo(self.name + '绑定窗口成功') self.log.writeinfo(self.name + str(hwnd)) # 激活窗口 self.yys.activate_window() self.log.writeinfo(self.name + '激活窗口成功') time.sleep(0.5) # 自检 debug_enable = conf.getboolean('others', 'debug_enable') if debug_enable: task = threading.Thread(target=self.yys.debug) task.start() def check_battle(self): # 检测是否进入战斗 self.log.writeinfo(self.name + '检测是否进入战斗') self.yys.wait_game_img('img\\ZI-DONG.png', self.max_win_time) self.log.writeinfo(self.name + '已进入战斗') def check_end(self): # 检测是否打完 self.log.writeinfo(self.name + '检测是战斗是否结束') self.yys.wait_game_img('img\\JIE-SU.png', self.max_win_time, 0.8) self.log.writeinfo(self.name + "战斗结束") def click_monster(self): # 点击怪物 pass def click_team(self, mode=1, number=0): """ 标记式神 :param mode 标记场景类型 1:御魂 2: 突破 """ # 标记式神 num = 0 if number > 0: num = number if self.team and self.team_id > 0: num = self.team_id if num > 0: # 100 1040 # 125 50 if mode == 1: # 御魂场景获取标记位置 min = (num - 1) * 105 + (num - 1) * 100 + 95 max = min + 50 pos = (min, 355), (max, 425) elif mode == 2: # 突破场景获取标记位置 pos = { 1: ((79, 385), (142, 418)), 2: ((315, 335), (360, 358)), 3: ((523, 270), (570, 325)), 4: ((715, 340), (750, 380)), 5: ((955, 400), (1055, 430)), }.get(num) start_time = time.time() while time.time() - start_time <= 3 and self.run: x1 = pos[0][0] - 100 y1 = pos[0][1] - 250 x2 = pos[1][0] + 100 y2 = pos[1][1] exp_pos = self.yys.find_color(((x1, y1), (x2, y2)), (134, 227, 96), 5) # print('颜色位置', exp_pos) if exp_pos != -1: self.log.writeinfo(self.name + ' 标记式神成功') return True else: # 点击指定位置并等待下一轮 self.yys.mouse_click_bg(*pos) self.log.writeinfo(self.name + '标记式神') time.sleep(0.4) self.log.writewarning(self.name + '标记式神失败') def click_until_multi(self, tag, *img_path, pos, pos_end=None, sleep_time=0.5): ''' 在某一时间段内,后台点击鼠标,直到出现某些图片出现 :param tag: 按键名 :param img_path: 图片路径 :param pos: (x,y) 鼠标单击的坐标 :param pos_end=None: (x,y) 若pos_end不为空,则鼠标单击以pos为左上角坐标pos_end为右下角坐标的区域内的随机位置 :step_time=0.5: 查询间隔 :return: 成功返回True, 失败退出游戏 ''' start_time = time.time() while time.time() - start_time <= self.max_op_time and self.run: result = self.yys.find_multi_game_img(*img_path) if result: self.log.writeinfo(self.name + '点击 ' + tag + ' 成功') return True else: # 点击指定位置并等待下一轮 self.yys.mouse_click_bg(pos, pos_end) self.log.writeinfo(self.name + '点击 ' + tag) time.sleep(sleep_time) self.log.writewarning(self.name + '点击 ' + tag + ' 失败!') # 提醒玩家点击失败,并在5s后退出 self.yys.activate_window() time.sleep(5) self.yys.quit_game() def click_until(self, tag, img_path, pos, pos_end=None, step_time=0.5, appear=True): ''' 在某一时间段内,后台点击鼠标,直到出现某一图片出现或消失 :param tag: 按键名 :param img_path: 图片路径 :param pos: (x,y) 鼠标单击的坐标 :param pos_end=None: (x,y) 若pos_end不为空,则鼠标单击以pos为左上角坐标pos_end为右下角坐标的区域内的随机位置 :step_time=0.5: 查询间隔 :appear: 图片出现或消失:Ture-出现;False-消失 :return: 成功返回True, 失败退出游戏 ''' # 在指定时间内反复监测画面并点击 start_time = time.time() self.log.writeinfo(self.name + '点击 ' + tag) while time.time() - start_time <= self.max_op_time and self.run: result = self.yys.find_game_img(img_path) if not appear: result = not result if result: self.log.writeinfo(self.name + '点击 ' + tag + ' 成功') return True else: # 点击指定位置并等待下一轮 # print("点击") self.yys.mouse_click_bg(pos, pos_end) # self.log.writeinfo(self.name + '点击 ' + tag) time.sleep(step_time) self.log.writewarning(self.name + '点击 ' + tag + ' 失败!') return False # 提醒玩家点击失败,并在5s后退出 # self.yys.activate_window() # time.sleep(5) # self.yys.quit_game() def activate(self): self.log.writewarning(self.name + '启动脚本') self.run = True self.yys.run = True def deactivate(self): self.log.writewarning(self.name + '手动停止脚本') self.run = False self.yys.run = False def slide_x_scene(self, distance): ''' 水平滑动场景 :return: 成功返回True; 失败返回False ''' x0 = random.randint(distance + 10, 1126) x1 = x0 - distance y0 = random.randint(436, 486) y1 = random.randint(436, 486) self.yys.mouse_drag_bg((x0, y0), (x1, y1)) logging.info(self.name + '水平滑动界面') def get_scene(self): ''' 识别当前场景 :return: 返回场景名称:1-庭院; 2-探索界面; 3-章节界面; 4-探索内 ''' # 拒绝悬赏 self.yys.rejectbounty() # 分别识别庭院、探索、章节页、探索内 maxVal, maxLoc = self.yys.find_multi_img('img/JIA-CHENG.png', 'img/JUE-XING.png', 'img/TAN-SUO.png', 'img/YING-BING.png') scene_cof = max(maxVal) if scene_cof > 0.97: scene = maxVal.index(scene_cof) return scene + 1 else: return 0 def switch_to_scene(self, scene): ''' 切换场景 :param scene: 需要切换到的场景:1-庭院; 2-探索界面; 3-章节界面; 4-探索内 :return: 切换成功返回True;切换失败直接退出 ''' scene_now = self.get_scene() logging.info(self.name + '目前场景:' + str(scene_now)) if scene_now == scene: return True if scene_now == 1: # 庭院中 if scene == 2 or scene == 3 or scene == 4: # 先将界面划到最右边 self.slide_x_scene(800) time.sleep(2) self.slide_x_scene(800) # 点击探索灯笼进入探索界面 self.click_until('探索灯笼', 'img/JUE-XING.png', *TansuoPos.tansuo_denglong, 2) # 递归 self.switch_to_scene(scene) if scene_now == 2: # 探索界面 if scene == 3 or scene == 4: # 点击最后章节 self.click_until('最后章节', 'img/TAN-SUO.png', *TansuoPos.last_chapter, 2) # 递归 self.switch_to_scene(scene) if scene_now == 3: # 章节界面 if scene == 4: # 点击探索按钮 self.click_until('探索按钮', 'img/YING-BING.png', *TansuoPos.tansuo_btn, 2) # 递归 self.switch_to_scene(scene) if scene_now == 4: # 探索内 if scene == 3: # 点击退出探索 self.click_until('退出按钮', 'img\\QUE-REN.png', *TansuoPos.quit_btn, 2) # 点击确认 self.click_until('确认按钮', 'img\\QUE-REN.png', *TansuoPos.confirm_btn, 2, False) # 递归 self.switch_to_scene(scene) def check_quit_game(self): if self.quit_time > 0: if time.time() - self.run_time > self.quit_time: # 切换到庭院 is_home = False while not is_home: maxVal, maxLoc = self.yys.find_img('img/JIA-CHENG.png') print("加成", maxVal) if maxVal > 0.9: is_home = True continue # 检查关闭 if self.yys.mouse_click_img('img/close.png'): time.sleep(0.3) # 检查返回 if self.yys.mouse_click_img('img/back.png'): time.sleep(0.5) # 检查确认 if self.yys.mouse_click_img('img/que-ding.png'): time.sleep(0.3) # 关闭加成 is_jiacheng = True self.click_until('加成', 'img/yu-hun-jia-cheng.png', *CommonPos.jia_cheng_btn, 0.3) while is_jiacheng: pos = self.yys.find_many_game_img('img/on-jia-cheng.png') print(pos) if len(pos) <= 0: is_jiacheng = False else: for item in pos: pos1 = (item[0] + 8, item[1] + 3) pos2 = (item[0] + 60, item[1] + 15) print(pos1, pos2) self.yys.mouse_click_bg(pos1, pos2) mood1 = ut.Mood(1) mood1.moodsleep() self.yys.quit_true_game()
import random import time from tools.logsystem import WriteLog log = WriteLog() class Mood: ''' 用于模拟随机的点击频率,每5分钟更换一次点击规律\n energetic: 状态极佳,点击延迟在1-1.5s\n joyful: 状态不错,点击延迟在1.3-2.1s\n normal: 状态一般,点击延迟在1.8-3s\n tired: 状态疲劳,点击延迟在2.5-4\n exhausted: CHSM,点击延迟在3-5s\n ''' def __init__(self, state=5): self.lastime = time.time() self.state = state Mood.mymood = { 1: (1000, 500), 2: (1300, 800), 3: (1800, 1200), 4: (2500, 1500), 5: (3000, 2000) } a = random.randint(1, self.state) log.writeinfo("Now you mood is level %d", a) self.lastmood = Mood.mymood[a]
class Fighter(GameScene): def __init__(self, name='', emyc=0, hwnd=0): ''' 初始化 :param name='': 打手名称 : param emyc=0: 点怪设置:0-不点怪 : param hwnd=0: 指定窗口句柄:0-否;其他-窗口句柄 ''' # 初始参数 self.emyc = emyc self.name = name self.run = True # 读取配置文件 conf = configparser.ConfigParser() conf.read('conf.ini') quit_game_enable = conf.getboolean('watchdog', 'watchdog_enable') self.max_op_time = conf.getint('watchdog', 'max_op_time') self.max_win_time = conf.getint('watchdog', 'max_win_time') self.mitama_team_mark = conf.getint('mitama', 'mitama_team_mark') self.max_times = conf.getint('DEFAULT', 'max_times') self.end_operation = conf.getint('DEFAULT', 'end_operation') self.run_times = 0 # 启动日志 self.log = WriteLog() # 绑定窗口 if hwnd == 0: hwnd = win32gui.FindWindow(0, u'阴阳师-网易游戏') self.yys = GameControl(hwnd, quit_game_enable) self.log.writeinfo(self.name + '绑定窗口成功') self.log.writeinfo(self.name + str(hwnd)) # 激活窗口 self.yys.activate_window() self.log.writeinfo(self.name + '激活窗口成功') time.sleep(0.5) # 绑定场景 # 自检 debug_enable = conf.getboolean('others', 'debug_enable') if debug_enable: task = threading.Thread(target=self.yys.debug) task.start() def check_battle(self): # 检测是否进入战斗 self.log.writeinfo(self.name + '检测是否进入战斗') self.yys.wait_game_img('img\\ZI-DONG.png', self.max_win_time) self.log.writeinfo(self.name + '已进入战斗') def check_end(self): ''' 检测是否打完 :return: 胜利页面返回0;奖励页面返回1 ''' self.log.writeinfo(self.name + '检测是战斗是否结束') if self.yys.wait_game_img_knn('img/SHENG-LI.png', self.max_win_time, False, 8): logging.info('战斗成功') return 0 elif self.yys.wait_game_img_knn('img/TIAO-DAN.png', 2, thread=20): logging.info('本轮战斗结束') return 1 def check_times(self): ''' 监测游戏次数是否达到最大次数 ''' self.run_times = self.run_times + 1 logging.info('游戏已运行'+str(self.run_times)+'次') if(self.run_times == self.max_times): if(self.end_operation == 0): logging.warning('关闭脚本(次数已满)...') self.run = False os._exit(0) elif(self.end_operation == 1): logging.warning('关闭游戏(次数已满)...') self.yys.quit_game() logging.warning('关闭脚本(次数已满)...') self.run = False os._exit(0) def get_reward(self, mood, state): ''' 结算处理 :param mood: 状态函数 :param state: 上一步的状态。0-战斗成功页面; 1-领取奖励页面 ''' if state == 0: self.click_until_knn('奖励', 'img/TIAO-DAN.png', ut.firstposition(), None, mood.get1mood()/1000, thread=20) start_time = time.time() while time.time()-start_time <= self.max_op_time and self.run: result = self.yys.find_game_img_knn('img/TIAO-DAN.png', thread=2) if not result: logging.info(self.name + '结算成功') return else: self.yys.mouse_click_bg(ut.secondposition()) self.log.writeinfo(self.name + '点击结算') mood.moodsleep() self.log.writewarning(self.name + '点击结算失败!') # 提醒玩家点击失败,并在5s后退出 self.yys.activate_window() time.sleep(5) self.yys.quit_game() def mitama_team_click(self): ''' 御魂标记己方式神 ''' num = self.mitama_team_mark if num > 0: # 100 1040 # 125 50 # 御魂场景获取标记位置 min = (num - 1) * 105 + (num - 1) * 100 + 95 max = min + 50 pos = (min, 355), (max, 425) start_time = time.time() while time.time() - start_time <= 3: x1 = pos[0][0] - 100 y1 = pos[0][1] - 250 x2 = pos[1][0] + 100 y2 = pos[1][1] exp_pos = self.yys.find_color( ((x1, y1), (x2, y2)), (134, 227, 96), 5) # print('颜色位置', exp_pos) if exp_pos != -1: self.log.writeinfo(self.name + '标记式神成功') return True else: # 点击指定位置并等待下一轮 self.yys.mouse_click_bg(*pos) self.log.writeinfo(self.name + '标记式神') time.sleep(0.4) self.log.writewarning(self.name + '标记式神失败') def click_monster(self): # 点击怪物 pass def click_until(self, tag, img_path, pos, pos_end=None, step_time=0.5, appear=True): ''' 在某一时间段内,后台点击鼠标,直到出现某一图片出现或消失 :param tag: 按键名 :param img_path: 图片路径 :param pos: (x,y) 鼠标单击的坐标 :param pos_end=None: (x,y) 若pos_end不为空,则鼠标单击以pos为左上角坐标pos_end为右下角坐标的区域内的随机位置 :step_time=0.5: 查询间隔 :appear: 图片出现或消失:Ture-出现;False-消失 :return: 成功返回True, 失败退出游戏 ''' # 在指定时间内反复监测画面并点击 start_time = time.time() while time.time()-start_time <= self.max_op_time and self.run: result = self.yys.find_game_img(img_path) if not appear: result = not result if result: self.log.writeinfo(self.name + '点击 ' + tag + ' 成功') return True else: # 点击指定位置并等待下一轮 self.yys.mouse_click_bg(pos, pos_end) self.log.writeinfo(self.name + '点击 ' + tag) ut.mysleep(step_time*1000) self.log.writewarning(self.name + '点击 ' + tag + ' 失败!') # 提醒玩家点击失败,并在5s后退出 self.yys.activate_window() time.sleep(5) self.yys.quit_game() def click_until_knn(self, tag, img_path, pos, pos_end=None, step_time=0.5, appear=True, thread=0): ''' 在某一时间段内,后台点击鼠标,直到出现某一图片出现或消失 :param tag: 按键名 :param img_path: 图片路径 :param pos: (x,y) 鼠标单击的坐标 :param pos_end=None: (x,y) 若pos_end不为空,则鼠标单击以pos为左上角坐标pos_end为右下角坐标的区域内的随机位置 :step_time=0.5: 查询间隔 :appear: 图片出现或消失:Ture-出现;False-消失 :thread: 检测阈值 :return: 成功返回True, 失败退出游戏 ''' # 在指定时间内反复监测画面并点击 start_time = time.time() while time.time()-start_time <= self.max_op_time and self.run: result = self.yys.find_game_img_knn(img_path, thread=thread) if not appear: result = not result if result: self.log.writeinfo(self.name + '点击 ' + tag + ' 成功') return True else: # 点击指定位置并等待下一轮 self.yys.mouse_click_bg(pos, pos_end) self.log.writeinfo(self.name + '点击 ' + tag) ut.mysleep(step_time*1000) self.log.writewarning(self.name + '点击 ' + tag + ' 失败!') # 提醒玩家点击失败,并在5s后退出 self.yys.activate_window() time.sleep(5) self.yys.quit_game() def activate(self): self.log.writewarning(self.name + '启动脚本') self.run = True self.yys.run = True def deactivate(self): self.log.writewarning(self.name + '手动停止脚本') self.run = False self.yys.run = False def slide_x_scene(self, distance): ''' 水平滑动场景 :return: 成功返回True; 失败返回False ''' x0 = random.randint(distance + 10, 1126) x1 = x0 - distance y0 = random.randint(436, 486) y1 = random.randint(436, 486) self.yys.mouse_drag_bg((x0, y0), (x1, y1)) logging.info(self.name + '水平滑动界面')
class Fighter: def __init__(self, name='', emyc=0, hwnd=0): ''' 初始化 :param name='': 打手名称 : param emyc=0: 点怪设置:0-不点怪 : param hwnd=0: 指定窗口句柄:0-否;其他-窗口句柄 ''' # 初始参数 self.emyc = emyc self.name = name self.run = True # 读取配置文件 conf = configparser.ConfigParser() conf.read('conf.ini') quit_game_enable = conf.getboolean('watchdog', 'watchdog_enable') self.max_op_time = conf.getint('watchdog', 'max_op_time') self.max_win_time = conf.getint('watchdog', 'max_win_time') # 启动日志 self.log = WriteLog() # 绑定窗口 if hwnd == 0: hwnd = win32gui.FindWindow(0, u'阴阳师-网易游戏') self.yys = GameControl(hwnd, quit_game_enable) self.log.writeinfo(self.name + '绑定窗口成功') self.log.writeinfo(self.name + str(hwnd)) # 激活窗口 self.yys.activate_window() self.log.writeinfo(self.name + '激活窗口成功') time.sleep(0.5) def check_battle(self): # 检测是否进入战斗 self.log.writeinfo(self.name + '检测是否进入战斗') self.yys.wait_game_img('img\\ZI-DONG.png', self.max_win_time) self.log.writeinfo(self.name + '已进入战斗') def check_end(self): # 检测是否打完 self.log.writeinfo(self.name + '检测是战斗是否结束') self.yys.wait_game_img('img\\JIE-SU.png', self.max_win_time) self.log.writeinfo(self.name + "战斗结束") def click_monster(self): # 点击怪物 pass def click_until(self, tag, img_path, pos, pos_end=None, step_time=0.5): ''' 在某一时间段内,后台点击鼠标,直到出现某一图片出现 :param tag: 按键名 :param img_path: 图片路径 :param pos: (x,y) 鼠标单击的坐标 :param pos_end=None: (x,y) 若pos_end不为空,则鼠标单击以pos为左上角坐标pos_end为右下角坐标的区域内的随机位置 :step_time=0.5: 查询间隔 :return: 成功返回True, 失败退出游戏 ''' # 在指定时间内反复监测画面并点击 start_time = time.time() while time.time() - start_time <= self.max_op_time and self.run: result = self.yys.find_game_img(img_path) if result: self.log.writeinfo(self.name + '点击 ' + tag + ' 成功') return True else: # 点击指定位置并等待下一轮 self.yys.mouse_click_bg(pos, pos_end) self.log.writeinfo(self.name + '点击 ' + tag) time.sleep(step_time) self.log.writewarning(self.name + '点击 ' + tag + ' 失败!') # 提醒玩家点击失败,并在5s后退出 self.yys.activate_window() time.sleep(5) self.yys.quit_game() def activate(self): self.log.writewarning(self.name + '启动脚本') self.run = True self.yys.run = True def deactivate(self): self.log.writewarning(self.name + '手动停止脚本') self.run = False self.yys.run = False
import os import ctypes from explore.explore import ExploreFight from mitama.fighter_driver import DriverFighter from mitama.fighter_passenger import FighterPassenger from mitama.single_fight import SingleFight from tools.logsystem import WriteLog # 设置 global mode global emyc global done #初始化对象 log = WriteLog() def init(): global section global mode global emyc global done try: # 选择打什么 section = int(input('\n选择刷什么(Ctrl-C跳过并单刷御魂:\n0-御魂\n1-探索\n')) log.writeinfo('Section = %d', section) if section == 0: # 御魂模式选择 mode=int(input('\n选择游戏模式(Ctrl-C跳过并单刷):\n0-单刷\n2-组队司机\n3-组队打手\n')) if(mode==1):