def fight_stage(stage_temp_list): if stage_temp_list is None or len(stage_temp_list) == 0: print('目标关卡未指定') exit(1) auto_adb = AutoAdb() # 判断是否已经在关卡中 in_enemy = PageUtils.in_enemy_page() if in_enemy: fight_all_enemy() return # 确定进入 timer = Timer() while True: print('\r扫描目标关卡中 ... %ds ' % timer.get_duration(), end='') loc = auto_adb.get_location(*stage_temp_list) if loc is not None: break print('%s √' % loc.temp_rel_path) loc.click() # 点击关卡图标 confirmed = confirm_stage_team() # 确认队伍 if not confirmed: # 如果队伍确认失败,则重新做一次 fight_stage(stage_temp_list)
def run(): print('每日任务开始。。。') print('目前仅支持 ”商船护卫“、”海域突进“、“斩首行动” 三个类别。') print('“战术研修”和“破交作战”由于战力要求和操控要求比较高,因此暂不能自动化。') print() adb = AutoAdb() task_list = [{ 'loc': Location(adb, None, 160, 400, '商船护卫'), 'day': [1, 4, 7] }, { 'loc': Location(adb, None, 370, 400, '海域突进'), 'day': [2, 5, 7] }, { 'loc': Location(adb, None, 900, 400, '斩首行动'), 'day': [3, 6, 7] }] week_day = datetime.datetime.now().weekday() + 1 for task in task_list: task_loc = task['loc'] if week_day not in task['day']: continue PageUtils.to_stage_page() adb.wait( 'temp_images/daily-task/daily-task/goto-daily-task.png').click() task_loc.click() Location(adb, None, 640, 400).click() # 执行方法 print('今天是周%d,%s开放' % (week_day, task_loc.remark)) TaskHelper(task_loc.remark).run() PageUtils.to_main_page()
def back(): temp_list = [ 'temp_images/page/back.png', # 返回按钮 'temp_images/page/back-2.png' # 返回按钮 ] loc = AutoAdb().get_location(*temp_list) if loc is not None: print('点击页面返回按钮') loc.click()
def to_stage_page(): adb = AutoAdb() if in_stage_page(): return True to_main_page() adb.click('temp_images/page/main-fight.png') # 可能正处在战斗关卡,自动战斗 fight = StageFight.wind_up_stage_fight() if fight: return to_stage_page() return True
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 deal_accident_when_provoke_enemy(): auto_adb = AutoAdb() # 自动战斗 res = auto_adb.click('temp_images/fight/auto-fight-confirm-1.png') if res: print('确认自律战斗') auto_adb.wait('temp_images/fight/auto-fight-confirm-2.png').click() # 处理途中获得道具的提示 auto_adb.click('temp_images/stage/get-tool.png') # 处理伏击 auto_adb.click('temp_images/stage/escape.png')
class Slider: # 滑动次数 num = 0 # adb auto_adb = AutoAdb() pos_list = [ [200, 200], # 左上角 [1100, 200], # 右上角 [1100, 600], # 右下角 [200, 600] # 左下角 ] def slider(self): print('滑动页面。 累积次数: %d.' % self.num) cursor_start = self.num % 4 cursor_end = (self.num + 1) % 4 pos_start = self.pos_list[cursor_start] pos_end = self.pos_list[cursor_end] self.auto_adb.swipe(*pos_start, *pos_end) # 每四次为一轮。从第二轮开始滑动会添加噪值 if 4 <= self.num < 8 or (self.num >= 8 and random.randint(0, 1) == 0): self.auto_adb.swipe(*pos_start, *pos_end) # +1 self.num += 1
class Slider: # 滑动次数 num = 0 # adb auto_adb = AutoAdb() pos_list = [ [200, 200], # 左上角 [1100, 200], # 右上角 [1100, 600], # 右下角 [200, 600] # 左下角 ] def slide(self): print('滑动页面。 累积次数: %d.' % self.num) cursor_start = self.num % 4 cursor_end = (self.num + 1) % 4 pos_start = self.pos_list[cursor_start] pos_end = self.pos_list[cursor_end] self.auto_adb.swipe(*pos_start, *pos_end) # 每四次为一轮。从第二轮开始滑动会添加噪值 if 4 <= self.num < 8 or (self.num >= 8 and random.randint(0, 1) == 0): self.auto_adb.swipe(*pos_start, *pos_end) # +1 self.num += 1 # 滑动完毕后等待,有时动画导致敌人无法判断 time.sleep(1) # 单向滑动 # direction 滑动方向,1、2、3、4分别代表上下左右 # num 滑动 次数 def slide_unidirectional(self, direction, num=1): if num is None or num <= 0: return if direction == 1: pos_start = self.pos_list[0] pos_end = self.pos_list[3] elif direction == 2: pos_start = self.pos_list[3] pos_end = self.pos_list[0] elif direction == 3: pos_start = self.pos_list[1] pos_end = self.pos_list[0] else: pos_start = self.pos_list[0] pos_end = self.pos_list[1] while True: if num == 0: break self.auto_adb.swipe(*pos_start, *pos_end) num -= 1
def run(cycle=True): num = 0 auto_adb = AutoAdb(test_device=True) res = auto_adb.check('temp_images/stage/in-stage.png') if res: # 如果已经在关卡中,则继续战斗 StageFight.fight_in_stage() num += 1 # 循环战斗 while True: if not cycle and num >= 1: break # 选择关卡 StageFight.pick_stage() # 开始战斗 StageFight.fight_in_stage() num += 1
def to_main_page(): adb = AutoAdb() temp_list = [ 'temp_images/page/main-page-button.png', # 主页按钮 'temp_images/page/close.png', # 关闭按钮 'temp_images/page/close-1.png', # 关闭按钮 'temp_images/page/back.png', # 返回按钮 'temp_images/page/back-2.png' # 返回按钮 ] while True: # 如果已经在主页则直接返回 if in_main_page(): return True # 尝试点击返回按钮 loc = adb.get_location(*temp_list) if loc is None: # 如果没找到合理的返回按钮,则点击左上角尝试 Location(adb, None, 10, 10).click() else: loc.click()
def fight(): adb = AutoAdb() # 战斗前各种按钮的点击 while True: if PageUtils.in_fight_page(): break click = adb.click('temp_images/fight/fight.png') if click: continue retired = PortUtils.check_port_full() if retired: # 如果发生了退役操作,则再次点击确认按钮 AutoAdb().wait('temp_images/fight/fight.png').click() continue low_mood = adb.check('temp_images/fight/low-mood.png') if low_mood: print('低心情状态,脚本终止') exit() print('战斗开始 >>>') return fight_finish()
class TaskHelper: adb = AutoAdb() task_name = None flag = 0 x_pos = 450 y_pos = 150 y_step = 160 def __init__(self, task_name): self.task_name = task_name def run(self): # 点击出击 Location(self.adb, None, self.x_pos, self.y_pos + self.y_step * self.flag).click() TeamLeader().auto_fight_confirm() # 观察是否已经耗尽机会 while True: # 出现出击按钮,说明已经进入关卡了 if self.adb.check('temp_images/fight/fight.png'): break # 如果出现没有机会提示,则说明没机会了 if self.adb.check( 'temp_images/daily-task/daily-task/no-chance.png', 'temp_images/daily-task/daily-task/no-chance-2.png', threshold=0.95): print('机会耗尽,%s结束' % self.task_name) return # 切换到最右边的队伍 while True: have_right = self.adb.click( 'temp_images/daily-task/daily-task/right-team.png') if not have_right: break # 出击 print('出击第 %d 关' % (self.flag + 1)) result = StageFight.fight() if not result: print('挑战失败,目标下移。。。') self.step_add() # 调用自己,继续战斗 self.run() def step_add(self): if self.flag >= 3: print('失败次数过多,停止战斗') exit() if self.flag < 3: print('关卡游标下移') self.flag += 1 print('失败次数累计:%d' % self.flag) time.sleep(1)
def confirm_stage_team(): adb = AutoAdb() timer = Timer() while True: print('\r确认关卡队伍中。。。 %ds ' % timer.get_duration(), end='') # 如果已经进入敌人列表界面,则跳出循环 if PageUtils.in_enemy_page(): print(' √') fight_all_enemy() # 战斗 return True button_list = [ 'temp_images/stage/immediate-start.png', # 立刻前往 'temp_images/stage/weigh-anchor.png', # 出击按钮 'temp_images/fight/fight-confirm.png' # 特殊关卡会提示更多 ] button_loc = adb.get_location(*button_list) if button_loc is not None: button_loc.click() port_full = PortUtils.check_port_full() if port_full: return False
def run(): print('日常巡检开始。。。') adb = AutoAdb() notice_loc = adb.get_location('temp_images/daily-task/notice.png') if not notice_loc: print('没有待处理的任务,巡检结束') return # 菜单位置 menu_pos = [ Location(adb, None, 628, 674, 'life-area'), # 生活区 Location(adb, None, 946, 674, 'missions'), # 任务 ] nearest_loc = notice_loc.get_nearest(menu_pos) nearest_loc.click() nearest_remark = nearest_loc.remark if nearest_remark == 'life-area': check_life_area(adb) elif nearest_remark == 'missions': deal_missions(adb) else: print('不能分辨出处理任务')
def fight_stage(stage_temp_list): if stage_temp_list is None or len(stage_temp_list) == 0: print('目标关卡未指定') exit(1) auto_adb = AutoAdb() # 判断是否已经在关卡中 wind_up_stage_fight() # 确定进入 timer = Timer() while True: print('\r扫描目标关卡中 ... %ds ' % timer.get_duration(), end='') loc = auto_adb.get_location(*stage_temp_list) if loc is not None: break print('%s √' % loc.temp_rel_path) loc.click() # 点击关卡图标 confirm_result = confirm_stage_team() # 确认队伍, 战斗 if confirm_result is None: # 如果关卡进入失败, 则重新尝试 print('关卡进入失败, 重新尝试...') fight_stage(stage_temp_list) return confirm_result
def test_device(): from common.AutoAdb import AutoAdb auto_adb = AutoAdb() print('ADB PATH >>>> ' + auto_adb.adb_path) try: subprocess.Popen([auto_adb.adb_path], stdout=subprocess.PIPE, stderr=subprocess.PIPE) except OSError: print('ADB 路径错误') exit(1) check_link(auto_adb) check_size(auto_adb) check_other(auto_adb) print()
def run(): PageUtils.to_main_page() adb = AutoAdb() adb.click('temp_images/daily-task/left-notice.png') complete = adb.get_location( 'temp_images/daily-task/delegation/complete.png').click() if not complete: print('没有委托任务') return while True: success_temp = [ 'temp_images/daily-task/delegation/success.png', # 委托成功 'temp_images/daily-task/delegation/success-1.png' # 点击继续 ] success = adb.get_location(*success_temp).click() if not success: break
def in_operation_page(): return AutoAdb().check('temp_images/page/in-operation.png')
def fight(): adb = AutoAdb() # 战斗前各种按钮的点击 while True: if PageUtils.in_fight_page(): break click = adb.click('temp_images/fight/fight.png') if click: continue retired = PortUtils.check_port_full() if retired: # 如果发生了退役操作,则再次点击确认按钮 AutoAdb().wait('temp_images/fight/fight.png').click() continue low_mood = adb.check('temp_images/fight/low-mood.png') if low_mood: print('低心情状态,脚本终止') exit() print('战斗开始 >>>') adb.wait('temp_images/fight/fight-finish.png', cycle_interval=5) # 战斗结束 fight_result = None ending_loc = Location(adb, None, 1160, 690) while True: if fight_result is None: # 处理新船 new_ship = adb.check('temp_images/fight/new-ship.png') if new_ship: print('发现新船!!') fight_result = True ending_loc.click() adb.click('temp_images/confirm-btn.png') continue # 处理失败 fail_confirm = adb.click('temp_images/fight/fail-confirm.png') if fail_confirm: fight_result = False # 战队难以成型时点击确定 adb.wait('temp_images/confirm-btn.png', max_wait_time=3).click() break # 持续点击右下角 ending_loc.click() # 回到 stage列表页面 或 敌人列表页面 也说明战斗已经结束 if adb.check( 'temp_images/page/in-stage.png', # stage列表 'temp_images/page/in-enemy.png', # enemy列表 'temp_images/page/main-page-button.png'): # 日常任务结束后的界面 fight_result = True break print('战斗胜利~(~ ̄▽ ̄)~' if fight_result else '战斗失败 >_<') # 战斗结束后可能出现紧急任务提示 # 由于是透明遮罩, 所以无法根据其他元素是否显示而做出反应, 只能等一定的时间 adb.wait('temp_images/confirm-btn.png', max_wait_time=2).click() return fight_result
def check_port_full(): auto_adb = AutoAdb() port_full = auto_adb.check('temp_images/port-full.png') if port_full: print('船坞已经满员了, 请整理') exit(1)
def provoke_enemy(): # 这里要多等待几秒, 因为经常会有个动画影响寻敌 time.sleep(3) auto_adb = AutoAdb() check = auto_adb.check('temp_images/stage/in-unit.png') if check: print('关卡已经结束') return False # 弹药为空时切换到第二舰队 if auto_adb.check('temp_images/stage/bullet-empty.png'): auto_adb.wait('temp_images/stage/switch-over.png').click(2) image_rel_path_list = TempUtils.get_temp_rel_path_list('temp_images/enemy') slider = Slider() while True: print('寻找敌人 ... ') enemy_loc = auto_adb.get_location(*image_rel_path_list) if enemy_loc is None: slider.slider() continue # 如果找到的是boss, 且当前是第一队, 则切换到第二队开始寻找敌人 is_boss = 'boss' in enemy_loc.temp_rel_path is_first_team = auto_adb.check('temp_images/stage/team-1.png') if is_boss and is_first_team: auto_adb.wait('temp_images/stage/switch-over.png').click(2) continue enemy_loc.click() # 等待进击按钮出现, 期间会不断处理意外情况, 如果指定时间内出现按钮, 则执行结束, 否则再次循环 res = auto_adb.wait('temp_images/fight/fight.png', max_wait_time=8, episode=deal_accident_when_provoke_enemy).click() if res: # 是否出现满员提示 check_port_full() return True else: # 如果点击后未进入确认界面, 说明那里不可到达, 此时去除image_rel_path_list中的值 image_rel_path_list.remove(enemy_loc.temp_rel_path)
from common.AutoAdb import AutoAdb from common.FightRecorder import FightRecorder 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() if __name__ == '__main__': AutoAdb(test_device=True) print('[连发模式] 持续寻找目标关卡', end='\n\n') run()
def deal_sos_sign(): adb = AutoAdb() adb.wait('temp_images/sos/sos-signal.png').click() # 将已经开启的潜艇关卡解决掉 goto_stage_page = adb.click('temp_images/sos/goto-stage-page.png') if goto_stage_page: # 有些情况会直接进入关卡,因此不需要“点击关卡” print('发现已经开启的关卡,即将进入战斗。。。') if PageUtils.in_enemy_page(): StageFight.fight_all_enemy() else: StageFight.fight_stage(['temp_images/sos/stage-icon.png']) return True # 搜索新的信号 print('搜索新的信号。。。') adb.click('temp_images/sos/search-signal.png') while True: if adb.check('temp_images/sos/no-chance.png'): print('已经没有新的信号,SOS关卡执行完毕,脚本退出') PageUtils.to_stage_page() exit() # 如果有确认按钮,则点击确认,前往关卡 adb.click('temp_images/confirm-btn.png') # 如果已经发现了关卡按钮,则点击 click_stage = adb.click('temp_images/sos/stage-icon.png') if click_stage: print('进入SOS关卡战斗。。。') confirmed = StageFight.confirm_stage_team() if not confirmed: continue return True
def fight_in_stage(): auto_adb = AutoAdb() while True: # 寻找敌人 res = provoke_enemy() if not res: break print('战斗开始 >>>') auto_adb.wait('temp_images/fight/fight-finish.png', cycle_interval=5) print(' 战斗结束 !') ending_loc = Location(auto_adb, None, 1040, 660) while True: in_stage = auto_adb.check('temp_images/stage/in-stage.png') in_unit = auto_adb.check('temp_images/stage/in-unit.png') if in_stage or in_unit: break new_ship = auto_adb.check('temp_images/fight/new-ship.png') if new_ship: print('发现新船!!') ending_loc.click() auto_adb.click('temp_images/fight/new-ship-confirm.png') continue fail_confirm = auto_adb.click('temp_images/fight/fail-confirm.png') if fail_confirm: input('战斗失败!! 请整理后按下任何按键以继续 ...') continue ending_loc.click() # 可能出现紧急任务提示 # 由于是透明遮罩, 所以无法根据其他元素是否显示而做出反应, 只能等一定的时间 auto_adb.wait('temp_images/fight/urgent-task.png', max_wait_time=3).click()
class TeamLeader: adb = AutoAdb() current_team_num = 1 # 当前是第几个队伍 # 判断当前是第几个队伍 # 此操作会导致地图发生位移!!因此,此方法被调用前的位置信息会失效 def get_team_num(self): # 先滑动到地图最左边 Slider().slide_unidirectional(4, 2) # 尝试匹配队伍 is_team_1 = self.adb.check("temp_images/stage/team-1.png") # 滑动回来 Slider().slide_unidirectional(3, 1) # 判断 if is_team_1: return 1 return 2 # 切换队伍。 def switch(self): self.adb.click("temp_images/stage/team-switch.png") self.current_team_num = 2 if self.current_team_num == 1 else 1 # 招惹敌军. # True 说明已经找到 # False 说明关卡结束 # 异常退出 说明关卡未结束, 可是无法分辨出敌人 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 accident_when_run(self): adb = self.adb # 自动战斗 res = adb.click('temp_images/fight/auto-fight-confirm-1.png') if res: print('确认自律战斗') adb.wait('temp_images/fight/auto-fight-confirm-2.png').click() # 处理途中获得道具的提示 adb.click('temp_images/stage/get-tool.png') # 处理伏击 adb.click('temp_images/stage/escape.png')
def in_main_page(): return AutoAdb().check('temp_images/page/in-main.png')
def fight_finish(): adb = AutoAdb() adb.wait('temp_images/fight/fight-finish.png', cycle_interval=5) # 战斗结束 fight_result = None ending_loc = Location(adb, None, 1160, 690) while True: if fight_result is None: # 处理新船 new_ship = adb.check('temp_images/fight/new-ship.png') if new_ship: print('发现新船!!') fight_result = True ending_loc.click() adb.click('temp_images/confirm-btn.png') continue # 处理失败 fail_confirm = adb.click('temp_images/fight/fail-confirm.png') if fail_confirm: fight_result = False # 战队难以成型时点击确定 adb.wait('temp_images/confirm-btn.png', max_wait_time=3).click() break # 持续点击右下角 ending_loc.click() # 回到 stage列表页面 或 敌人列表页面 也说明战斗已经结束 if adb.check( 'temp_images/page/in-stage.png', # stage列表 'temp_images/page/in-enemy.png', # enemy列表 'temp_images/page/in-daily.png'): # 日常任务结束后的界面 fight_result = True break if adb.check('temp_images/page/in-operation.png'): print('误入演习界面,退出。。。') PageUtils.back() continue print('战斗胜利~(~ ̄▽ ̄)~' if fight_result else '战斗失败 >_<') # 战斗结束后可能出现紧急任务提示 # 由于是透明遮罩, 所以无法根据其他元素是否显示而做出反应, 只能等一定的时间 adb.wait('temp_images/confirm-btn.png', max_wait_time=2).click() return fight_result
def in_stage_page(): return AutoAdb().check('temp_images/page/in-stage.png')
def in_fight_page(): return AutoAdb().check('temp_images/page/in-fighting.png')
def in_enemy_page(): return AutoAdb().check('temp_images/page/in-enemy.png')