def check_policy(self): if not self.auto_policy: return # 看看政策中心那里有没有冒绿色箭头气泡 if len(UIMatcher.findGreenArrow(self.d.screenshot(format="opencv"))): # 打开政策中心 self.d.click(0.206, 0.097) mid_wait() # 确认升级 self.d.click(0.077, 0.122) # 拉到顶 self._slide_to_top() # 开始找绿色箭头,找不到就往下滑,最多划5次 for i in range(5): screen = self.d.screenshot(format="opencv") arrows = UIMatcher.findGreenArrow(screen) if len(arrows): x, y = arrows[0] self.d.click(x, y) # 点击这个政策 short_wait() self.d.click(0.511, 0.614) # 确认升级 print("[%s] Policy upgraded. ++++++" % time.asctime()) break # 如果还没出现绿色箭头,往下划 else: self.d.swipe(0.5, 0.8, 0.5, 0.3, duration=0.3) self.d.click(0.5, 0.5) # 点击一下屏幕正中间,使其停止滑动 self._back_to_main()
def _Move_good_IOS(self): goods = self._bd["gds"] for good in self.harvest_filter: img = UIMatcher.getLittleSquare(self._Sshot(), self._pos_good[good], scale=2) UIMatcher.saveScreen(img, good) for target in goods.keys(): imageB = cv2.imread(target.value, 1) #msg("SSIM: {} Target {}".format(score,str(target))) result = UIMatcher.find(img, imageB, criteria=diff_situation(good, target)) if result: msg(str(target) + " move to " + str(goods[target])) position = self.pos[goods[target]] #Pout(sx,sy,ex,ey) self._move_good_by_id(good, position, times=4) #self._drag(sx, sy, ex , ey,0.5) break if not self._DEBUG: os.remove("s" + str(good) + ".png")
def start(self): NomoreTrain = False n = random.randint(95, 105) n2 = 1 Start_Time = time.time() # Initial Building pos and their level self._Initial_Building() self._AssignGoodsPosition() # Test crop the goods if self._DEBUG: #self._Test() UIMatcher.saveScreen(self._Sshot()) pass while True: if n2 % n == 0: print(self) # 升级建筑 self._upgrade_building() # Check if it is in the game self._runApp() # Swipe the screen to get the gold self._swipe() # Harvest the goods if not NomoreTrain: now = datetime.datetime.now().hour #识别到没有火车的标志 或者 五分钟内 没有搬运货物 就不再检测 if self._No_more_train() or ( round(time.time() - Start_Time) >= 300 and self._count["harvest"] == 0): msg("No more Train, Turn off harvest, set NomoreTrain" + str(NomoreTrain)) NomoreTrain = True if NomoreTrain and datetime.datetime.now().hour == 9: NomoreTrain = False msg("Reset NomoreTrain " + str(NomoreTrain)) self._harvest(NomoreTrain) # 判断是否可升级政策 #self.check_policy() # 判断是否可完成任务 self._check_task() # 判断是否有可点商品 self._red_packet() # 简单粗暴的方式,处理 “XX之光” 的荣誉显示。 # 不管它出不出现,每次都点一下 self._cross_out() n2 += 1
def start(self): """ 启动脚本,请确保已进入游戏页面。 """ tmp_upgrade_last_time = time.time() logger.info("Start Working") while True: # 检查是否有键盘事件 if not self._need_continue(): break # 进入命令模式后不继续执行常规操作 if self.command_mode: continue # 更新配置文件 self.config.refresh() # 在下午五点以后再开始拿火车,收益最大化 # if datetime.now().hour > 17: if True: logger.info("Start matching goods") # 获取当前屏幕快照 screen = self.d.screenshot(format="opencv") # 判断是否出现货物。 has_goods = False for target in self.config.goods_2_building_seq.keys(): has_goods |= self._match_target(screen, target) if has_goods: UIMatcher.write(screen) # pass logger.info("End matching") # 简单粗暴的方式,处理 “XX之光” 的荣誉显示。 # 当然,也可以使用图像探测的模式。 self.d.click(550, 1650) # 滑动屏幕,收割金币。 # logger.info("swipe") self._swipe() # 升级建筑 tmp_upgrade_interval = time.time() - tmp_upgrade_last_time if tmp_upgrade_interval >= self.config.upgrade_interval_sec: if self.config.upgrade_type_is_assign is True: self._assigned_uprade() else: self._upgrade() tmp_upgrade_last_time = time.time() else: logger.info( f"Left {round(self.config.upgrade_interval_sec - tmp_upgrade_interval, 2)}s to upgrade" ) time.sleep(self.config.swipe_interval_sec) logger.info('Sub process end')
def _has_train(self): x, y = self._btn["P_Train"] screen = self._Sshot() R, G, B = UIMatcher.getPixel(screen, x, y) if r_color((R, G, B), TRAIN_COLOR_IOS, diff=10): return True if self._DEBUG: msg("No train (" + str(R) + "," + str(G) + "," + str(B) + ")") UIMatcher.saveScreen(self._Sshot(), "has_train") return False
def _No_more_train(self): x, y = self._btn["P_NoMoreTrain"] R, G, B = UIMatcher.getPixel(self._Sshot(), x, y) if r_color((R, G, B), NO_MORE_TRAIN_IOS): self._tap(x, y) ms() x2, y2 = self._btn["B_NoMoreTrain"] self._tap(x2, y2) ms() return True if self._DEBUG: msg("No More train (" + str(R) + "," + str(G) + "," + str(B) + ")") UIMatcher.saveScreen(self._Sshot(), "No_more_train") return False
def guess_good(self, good_id): ''' 按住货物,探测绿光出现的位置 这一段应该用numpy来实现,奈何我对numpy不熟。。。 ''' diff_screens = self.get_screenshot_while_touching(GOODS_POSITIONS[good_id]) return UIMatcher.findGreenLight(diff_screens)
def _have_redpocket_third(self): print("test_third") while True: screen = self.d.screenshot(format="opencv") R, G, B = UIMatcher.getPixel(screen, 480 / 533, 312 / 948) if R >= 180 and G < 110: self.d.click(480 / 533, 312 / 948) while True: screen_1 = self.d.screenshot(format="opencv") R_1, G_1, B_1 = UIMatcher.getPixel(screen_1, 0.487, 0.831) if R_1 > G_1: self.d.click(0.811, 0.263) else: break else: break
def guess_good(self, good_id): ''' 按住货物,探测绿光出现的位置 这一段应该用numpy来实现,奈何我对numpy不熟。。。 ''' diff_screen = self.get_screenshot_while_touching( GOODS_POSITIONS[good_id]) pos_ID = 0 for pos_ID in range(1, 10): # print('hhhh') x, y = GOODS_SAMPLE_POSITIONS[pos_ID] lineCount = 0 for line in range(-2, 6): #划8条线, 任意2条判定成功都算 R, G, B = 0, 0, 0 for i in range(-10, 10): # 取一条线上20个点,取平均值 r, g, b = UIMatcher.getPixel(diff_screen, (x + 1.73 * i) / 540, (y + line + i) / 960) R += r G += g B += b # 如果符合绿光的条件 if R / 20 > 220 and G / 20 < 70: lineCount += 1 if lineCount > 1: return pos_ID return 0
def _Is_Btn_Upgrade(self): x, y = self._btn["B_Upgrade"] R, G, B = UIMatcher.getPixel(self._Sshot(), x, y) if B > R: return False elif B < R: return True
def _match_target(self, target: TargetType): """ 探测货物,并搬运货物。 """ cargoPos = [[660, 1640], [0.771 * 1080, 0.815 * 1920], [0.895 * 1080, 0.77 * 1920]] for cargo in cargoPos: screen = self.d.screenshot(format="opencv") result = UIMatcher.match(screen) if result is None: return # 获取当前屏幕快照 # 由于 OpenCV 的模板匹配有时会智障,故我们探测次数实现冗余。 # 使用 OpenCV 探测货物。 # 若无探测到,终止对该货物的探测。 # 实现冗余的原因:返回的货物屏幕位置与实际位置存在偏差,导致移动失效 for i in range(3): sx, sy = cargo for cnt in range(9): ex, ey = self._get_position(cnt + 1) time.sleep(.3) self.d.swipe(sx, sy, ex, ey)
def _match_target(self, screen, target: TargetType): """ 探测货物,并搬运货物。 """ # 由于 OpenCV 的模板匹配有时会智障,故我们探测次数实现冗余。 counter = 6 logged = False while counter != 0: counter = counter - 1 # 使用 OpenCV 探测货物。 result = UIMatcher.match(screen, target) # 若无探测到,终止对该货物的探测。 # 实现冗余的原因:返回的货物屏幕位置与实际位置存在偏差,导致移动失效 if result is None: break rank = result[-1] result = result[:2] sx, sy = result # 获取货物目的地的屏幕位置。 ex, ey = self._get_target_position(target) if not logged: logger.info(f"Detect {target} at ({sx},{sy}), rank: {rank}") logged = True # 搬运货物。 self.d.swipe(sx, sy, ex, ey) # 侧面反映检测出货物 return logged
def _match_target(self, target: TargetType): """ 探测货物,并搬运货物。 """ # 获取当前屏幕快照 screen = self.d.screenshot(format="opencv") # 由于 OpenCV 的模板匹配有时会智障,故我们探测次数实现冗余。 counter = 5 while counter != 0: counter = counter - 1 # 使用 OpenCV 探测货物。 result = UIMatcher.match(screen, target) # 若无探测到,终止对该货物的探测。 # 实现冗余的原因:返回的货物屏幕位置与实际位置存在偏差,导致移动失效 if result is None: break # 在 trainMode 下设置搬运成果。 if self.trainMode: self.isHarvest = True sx, sy = result # 获取货物目的地的屏幕位置。 ex, ey = self._get_target_position(target) # 搬运货物。 self.d.swipe(sx, sy, ex, ey)
def check_equipment(image, template_path): """ 查找装备 :param template_path: 模板目录 :return: {'r': 相似度, 'x': x坐标, 'y': y坐标, 'path': 模板路径} """ THRESHOLD = 0.55 found = None return_list = list() screen = image # 遍历所有的图片寻找模板 for imagePath in glob.glob(template_path + "/*"): log.debug("> " + imagePath) # result = UIMatcher.multi_scale_template_match(screen, imagePath) h, w = screen.shape[:2] item_w = w / 10 scale = 128 / item_w result = UIMatcher.multi_scale_template_match( screen, imagePath, min_scale=scale, max_scale=scale, step=1) if result['r'] > THRESHOLD: result['path'] = imagePath return_list.append(result) return return_list
def test_template_match(self): app = Automator() screenshot = app.d.screenshot(format="opencv") res = UIMatcher.template_match(screenshot, "../tw_img/icon_guild.jpg") self.assertLessEqual(THRESHOLD, res['r']) self.assertLessEqual(0, res['x']) self.assertLessEqual(0, res['y']) print(res)
def _select_min_building(self): screen = self.d.screenshot(format="opencv") screen = UIMatcher.pre(screen) min_level = float('inf') min_building_seq = None for key in self.__find_selected_building_seq(): pos = prop.BUILDING_LEVEL_POS[key] tmp = UIMatcher.cut(screen, pos) tmp = UIMatcher.plain(tmp) tmp = UIMatcher.fill_color(tmp) tmp = UIMatcher.plain(tmp) txt = UIMatcher.image_to_txt(tmp, plus='-l chi_sim --psm 7') txt = UIMatcher.normalize_txt(txt) try: level = int(txt) logger.info(f'{self.config.building_pos[key - 1]} tesser -> {level}') except Exception: logger.warning(f'{self.config.building_pos[key - 1]} tesser -> {txt}') continue if level < min_level: min_level = level min_building_seq = key # 一个屋子的等级都没拿到 if min_building_seq is None: res = choice(list(prop.BUILDING_POS.keys())) logger.warning(f'No tesseract result, random to {self.config.building_pos[res - 1]}') return res else: logger.info(f'Minimum level is {min_level} from {self.config.building_pos[min_building_seq - 1]}') return min_building_seq
def _upgrade_to(self, target_level): """ target_level: 目标等级 升至 target_level 级 利用 Tesseract 识别当前等级后点击升级按钮 target_level - 当前等级次 """ screen = self._safe_screenshot() screen = UIMatcher.pre_building_panel(screen) tmp = UIMatcher.cut(screen, prop.BUILDING_INFO_PANEL_LEVEL_POS, (120, 50)) # import cv2 # cv2.imwrite("./tmp/screen.jpg", screen) tmp = UIMatcher.plain(tmp) tmp = UIMatcher.fill_color(tmp) tmp = UIMatcher.plain(tmp) txt = UIMatcher.image_to_txt(tmp, plus='-l chi_sim --psm 7') txt = UIMatcher.normalize_txt(txt) try: cur_level = int(txt) logger.info(f'Current level -> {cur_level}') except Exception: logger.warning(f'Current level -> {txt}') return click_times = target_level - cur_level self._upgrade_times(click_times)
def test_multi_scale_template_match(self): app = Automator() screenshot = app.d.screenshot(format="opencv") res = UIMatcher.multi_scale_template_match(screenshot, "../equipment_img/115011.webp") # res = UIMatcher.multi_scale_template_match(screenshot, "../tw_img/icon_guild.jpg") self.assertLessEqual(THRESHOLD, res['r']) self.assertLessEqual(0, res['x']) self.assertLessEqual(0, res['y']) print(res)
def _check_task(self): if not self.auto_task: return x, y = self._btn["B_Task"] self._tap(x, y) s(2) x2, y2 = self._btn["B_Finish_Task"] R, G, B = UIMatcher.getPixel(self._Sshot(), x2, y2) if r_color((R, G, B), TASK_B_FINISH_IOS): self._tap(x2, y2) ss() if self._DEBUG: msg("Task Finished Color(" + str(R) + "," + str(G) + "," + str(B) + ")") UIMatcher.saveScreen(self._Sshot(), "Finished") self._cross_out() return False
def divide(image_info, screen): screen = UIMatcher.RotateClockWise90(screen) for image in image_info: x0, x1, y0, y1 = image['x0'], image['x1'], image['y0'], image['y1'] item_img = screen[y0:y1, x0:x1] # item_name = re.findall('([0-9]*\.webp)', image['path'])[0] # print(item_name) # save_path = os.path.join(os.path.abspath(os.path.curdir), 'res', item_name) # cv2.imwrite(save_path, item_img) image['image'] = item_img
def _have_redpocket_first(self): # while True: # self.d.click(84/533,688/940) print("test_first") while True: screen = self.d.screenshot(format="opencv") R, G, B = UIMatcher.getPixel(screen, 152 / 533, 312 / 948) print(R, G, B) if R >= 180 and G < 110: self.d.click(152 / 533, 312 / 948) while True: screen_1 = self.d.screenshot(format="opencv") R_1, G_1, B_1 = UIMatcher.getPixel(screen_1, 0.487, 0.831) if R_1 > G_1: self.d.click(0.184, 0.263) else: break else: break
def _DeterminePos_Android(self, pos, pressed_time=0.2): screen_before = self._Sshot() x, y = self._pos_good[pos] x, y = (x * self.dWidth, y * self.dHeight) self.d.touch.down(x, y) time.sleep(pressed_time) screen_after = self._Sshot() self.d.touch.up(x, y) diff_screens = (screen_before, screen_after) result = UIMatcher.findGreenLight(diff_screens, self.pos) return result
def _match_mission(self): screen = my_screenshot_with_cache(self.d, format="opencv") print(screen) result = UIMatcher.match(screen, TargetType.Mission_done) if result is None: return self.d.click(*prop.MISSION_BTN) time.sleep(1) self.d.click(*prop.MISSION_DONE_BTN) time.sleep(1) self.d.click(*prop.MISSION_CLOSE_BTN)
def check_task(self): if not self.auto_task: return # 看看任务中心有没有冒黄色气泡 screen = self.d.screenshot(format="opencv") if UIMatcher.findTaskBubble(screen): self.d.click(0.16, 0.84) # 打开城市任务 short_wait() self.d.click(0.51, 0.819) # 点击 完成任务 print("[%s] Task finished. ++++++" % time.asctime()) self._back_to_main()
def _check_good(self): screen_before = my_screenshot_with_cache(self.d, format="opencv") h = len(screen_before) w = len(screen_before[0]) good_id_list = UIMatcher.detect_cross(screen_before) for good_id in good_id_list: two_screen = self._get_screenshot_while_touching( prop.GOODS_POSITIONS[good_id], screen_before=screen_before) good_dest = UIMatcher.find_green_light(two_screen) if 1 <= good_dest <= 9 and good_dest in self.config.goods_2_building_seq.values( ): dx, dy = self._get_position(good_dest) sx, sy = prop.GOODS_POSITIONS[good_id] sx = sx * w sy = sy * h logger.info( f'Detect good {good_id} -> {good_dest}: ({sx},{sy}) -> ({dx},{dy})' ) self._carry_good((sx, sy), (dx, dy))
def _red_packet(self): if self._ar: x, y = self._btn["B_Store"] x2, y2 = self._btn["B_Build"] if r_color(UIMatcher.getPixel(self._Sshot(), x, y), RED_PACKET, 10): self._tap(x, y) ms() if r_color(UIMatcher.getPixel(self._Sshot(), x2, y2), BLUE_MENU): for px, py in self._btn["P_redpacket"]: while r_color( UIMatcher.getPixel(self._Sshot(), px, py), RED_PACKET, 15): self._tap(px, py) ms() self._cross_out(10) self._count["red_packet"] += 1 msg("Detected RED_PACKET, TAPS") elif self._DEBUG: msg("RED_PACKET " + str(x) + "," + str(y)) elif self._DEBUG: UIMatcher.saveScreen(self._Sshot(), "RED_PACKET") ss() self._tap(x2, y2) ms() if r_color(UIMatcher.getPixel(self._Sshot(), x2, y2), BLUE_MENU): self._tap(x2, y2)
def start(self): start_time = time.time() sleep_time = 3 # 两次检测之间的间隔 no_train_counter = 0 # 连续没有检测到火车的次数 train_image = cv2.imread('Train.jpg') good_counter = 0 restart_counter = 0 while True: if self.mode != '拉货': # 进入商店 self.d.click(424, 1822) # 开始点击,但考虑到运行速度,未添加次数限制,所以不会自动停下,请手动重启脚本 self.d.click(*self.positions[self.mode]) else: # 判断是否出现货物。 Screen = self.d.screenshot(format="opencv") self.d.click(550, 1650) # 滑动屏幕,收割金币。 self._swipe() if UIMatcher.Detect_signal_object(Screen, train_image): print('火车来了!') no_train_counter = 0 success_counter = 0 time.sleep(1) # 确保火车停了下来 screen = self.d.screenshot(format="opencv") for target in TargetType: if success_counter > 2: print('成功找到3个货物,提前结束!') break if self._match_target(target, screen): print(f'寻找{target.name}-------------------成功') success_counter += 1 good_counter += 1 else: print(f'寻找{target.name}-------------------失败') # if target in self.ban_list: print(f'重启游戏...') restart_counter += 1 self.d.app_stop("com.tencent.jgm") self.d.app_start("com.tencent.jgm") time.sleep(20) else: no_train_counter += 1 if no_train_counter >= 20: print(f'连续{no_train_counter * sleep_time}s没有检测到火车,结束脚本!') print( f'脚本运行期间一共\n运行了--------------------{(time.time() - start_time) / 60}min\n拉取了--------------------{good_counter}次货物\n重启了--------------------{restart_counter}次') return time.sleep(sleep_time)
def _match_target(self, target: TargetType, screen): # 探测货物,并搬运货物。 result = UIMatcher.match(screen, target) if result is not None: sx, sy = result # 获取货物目的地的屏幕位置。 ex, ey = self._get_target_position(target) # 搬运货物。 for j in range(2): self.d.swipe(sx, sy, ex, ey) return True return False
def _detect_cross(self, screen, positon): x, y = positon # print(x,y) R, G, B = 0, 0, 0 for i in range(-4, 4): # 取一条45度线线上8个点,取平均值 r, g, b = UIMatcher.getPixel(screen, x + i / self.dWidth, y + i / self.dHeight) R += r G += g B += b # 如果符合叉叉(白色)的条件 if R / 8 > 250 and G / 8 > 250 and B / 8 > 250: return True return False
def _Initial_Building(self): if self._bd["pos"] == None: x, y = self._btn["B_Upgrade"] if not self._Is_Btn_Upgrade(): self._tap(x, y) for i in range(9): sx, sy = self.pos[i + 1] self._tap(sx, sy) building = UIMatcher.BdOrc(self._Sshot(), self._btn["R_Names"]) if not building == None and type(building) is str: self._bd["lvl"][i + 1], self._bd["pos"][ i + 1] = building.split("级") self._tap(x, y) if self._Is_Btn_Upgrade(): self._tap(x, y) else: for i in range(9): self._bd["lvl"][i + 1] = 0