def provoke_enemy(self): adb = self.adb # 这里要多等待几秒, 因为经常会有个动画影响寻敌 time.sleep(3) if PageUtils.in_stage_page(): # 关卡已经结束 return False # 弹药为空且当前是第一队时切换队伍 if self.current_team_num == 1 and adb.check( 'temp_images/stage/bullet-empty.png'): self.switch() # 页面滑动工具类 slider = Slider() # 敌人的模板列表 image_rel_path_list = PathUtils.get_temp_rel_path_list( 'temp_images/enemy') while True: print('寻找敌人 ... ') enemy_loc = adb.get_location(*image_rel_path_list) if enemy_loc is None: # 有时没找到敌人是已经进入确认界面了 if adb.check('temp_images/fight/fight.png'): return True # 滑动界面寻找敌人 slider.slide() continue # 如果当前是第一队, 且找到的是boss, 则切换到第二队开始寻找敌人 if self.current_team_num == 1 and 'boss' in enemy_loc.temp_rel_path: self.switch() continue # 有时敌人离状态栏太近,这时加大Y轴 if enemy_loc.pos_y < 65: enemy_loc.pos_y = 65 # 点击敌人位置 enemy_loc.click() # 等待进击按钮出现, 期间会不断处理意外情况, 如果指定时间内出现按钮, 则执行结束, 否则再次循环 res = adb.wait('temp_images/fight/fight.png', max_wait_time=8, episode=self.accident_when_run).is_valuable() if res: return True else: # 如果点击后未进入确认界面, 说明那里不可到达, 此时去除image_rel_path_list中的值 image_rel_path_list.remove(enemy_loc.temp_rel_path) # 如果list为空了,则恢复到原有列表 if len(image_rel_path_list) == 0: image_rel_path_list = PathUtils.get_temp_rel_path_list( 'temp_images/enemy')
def run(): StageFight.wind_up_stage_fight() adb = AutoAdb(test_device=True) temp_list = PathUtils.get_temp_rel_path_list( 'temp_images/target-stage-hard') while True: # 如果发现次数为0,则终止 if adb.click('temp_images/stage/no-chance-for-hard.png'): print('困难关卡机会已用尽,程序终止') break StageFight.fight_stage(temp_list) print('困难关卡已经结束')
def run(): # 计数 num = 0 # 最大通关次数 max_stage_fight_times = int(ConfigUtils.get('max_stage_fight_times')) # 循环战斗 while True: # 选择关卡 开始战斗 target_stage_list = PathUtils.get_temp_rel_path_list('temp_images/target-stage') StageFight.fight_stage(target_stage_list) # 计数 num += 1 print('通关次数累计:%d' % num, end='\n\n') if max_stage_fight_times is not None and num >= max_stage_fight_times: print('已达最大通关次数 %d,结束运行' % max_stage_fight_times) exit()
def __init__(self): # 读取配置文件 config_file = PathUtils.get_work_dir() + '/config.ini' if not os.path.isfile(config_file): print( '配置文件 config.ini 不存在,请将程序根目录的 config_temp.ini 文件拷贝一份并命名为 config.ini。注意要自行调整其中的配置项。' ) exit(1) if not os.access(config_file, os.R_OK): print( '配置文件 config.ini 不可读,请将程序根目录的 config_temp.ini 文件拷贝一份并命名为 config.ini。注意要自行调整其中的配置项。' ) exit(1) cp = ConfigParser() cp.read(config_file, encoding='utf-8') self._cp = cp
def get_location(self, *temp_rel_path_list, threshold=threshold): self.screen_cap() sp_gray = cv2.imread(self.screen_pic_path, cv2.COLOR_BGR2BGRA) for temp_rel_path in temp_rel_path_list: temp_abs_path = PathUtils.get_abs_path(temp_rel_path) temp_gray = cv2.imread(temp_abs_path, cv2.COLOR_BGR2BGRA) res = cv2.matchTemplate(sp_gray, temp_gray, cv2.TM_CCOEFF_NORMED) _, max_val, _, max_loc = cv2.minMaxLoc(res) if max_val < threshold: continue h, w, _ = cv2.imread(temp_abs_path).shape x = max_loc[0] + w / 2 y = max_loc[1] + h / 2 return Location(self, temp_rel_path, x, y) return None
def run(): # 计数 fight_recorder = FightRecorder() # 最大通关次数 max_stage_fight_times = int(ConfigUtils.get('max_stage_fight_times')) # 循环战斗 while True: # 选择关卡 开始战斗 target_stage_list = PathUtils.get_temp_rel_path_list('temp_images/target-stage') fight_result = StageFight.fight_stage(target_stage_list) # 计数 fight_recorder.append(fight_result) fight_recorder.print_recorder() # 连续失败两次就停止战斗 if fight_recorder.get_last_fail_count() >= 2: print('连续 2 次关卡战斗失败, 为了避免更多损失脚本自动退出') exit() if max_stage_fight_times is not None and fight_recorder.get_total_count() >= max_stage_fight_times: print('已达最大通关次数 %d,结束运行' % max_stage_fight_times) exit()
def __init__(self, test_device=False): self.adb_path = PathUtils.get_work_dir() + '/adb/adb.exe' if test_device: AutoAdbCheck.test_device(self)
class AutoAdb: threshold = 0.8 wait_time = 1 screen_pic_path = PathUtils.get_cache_dir() + '/screen.png' def __init__(self, test_device=False): self.adb_path = PathUtils.get_work_dir() + '/adb/adb.exe' if test_device: AutoAdbCheck.test_device(self) def run(self, raw_command): adb_host_port = ConfigUtils.get('adb_host_port') command = '%s -s %s %s' % (self.adb_path, adb_host_port, raw_command) res = os.popen(command) return res.buffer.read().decode('utf-8').strip() def screen_cap(self): self.run('exec-out screencap -p > ' + self.screen_pic_path) def get_location(self, *temp_rel_path_list, threshold=threshold): self.screen_cap() sp_gray = cv2.imread(self.screen_pic_path, cv2.COLOR_BGR2BGRA) for temp_rel_path in temp_rel_path_list: temp_abs_path = PathUtils.get_abs_path(temp_rel_path) temp_gray = cv2.imread(temp_abs_path, cv2.COLOR_BGR2BGRA) res = cv2.matchTemplate(sp_gray, temp_gray, cv2.TM_CCOEFF_NORMED) _, max_val, _, max_loc = cv2.minMaxLoc(res) if max_val < threshold: continue h, w, _ = cv2.imread(temp_abs_path).shape x = max_loc[0] + w / 2 y = max_loc[1] + h / 2 return Location(self, temp_rel_path, x, y) return None def check(self, *temp_rel_path_list): loc = self.get_location(*temp_rel_path_list) return loc is not None def click(self, temp_rel_path, threshold=threshold, wait_time=wait_time): loc = self.get_location(temp_rel_path, threshold=threshold) if loc is None: return False return loc.click(wait_time) def swipe(self, start_x, start_y, end_x, end_y, duration=1500): self.run('shell input swipe %d %d %d %d %d' % (start_x, start_y, end_x, end_y, duration)) def wait(self, temp_rel_path, threshold=threshold, cycle_interval=0, max_wait_time=None, episode=None): timer = Timer() while True: duration = timer.get_duration() print('\r > wait %s ... %ds ' % (temp_rel_path, duration), end='') if max_wait_time is not None and 0 < max_wait_time < duration: print(' ×', flush=True) return Location(self, None, None, None) if episode is not None: try: episode() except Exception as e: print('过程方法执行异常') print(e) loc = self.get_location(temp_rel_path, threshold=threshold) if loc is not None: print(' √', flush=True) return loc if cycle_interval > 0: time.sleep(cycle_interval)
def get(key, section='default', fallback=None): cp = ConfigParser() cp.read(PathUtils.get_work_dir() + '/config.ini', encoding='utf-8') return cp.get(section, key, fallback=fallback)