def match_and_click(template, source=None, delete_after_match=False, match_threshold=0.6): global impl, special_random_position_delta if source is None: source = get_new_capture() max_val, tl_loc, br_loc = cv_util.match_template(template, source) if delete_after_match: delete_file(source) if max_val > match_threshold: x = (br_loc[0] + tl_loc[0]) / 2 y = (br_loc[1] + tl_loc[1]) / 2 random_delta_x, random_delta_y = 0, 0 for delta in special_random_position_delta: if delta[0](template): random_delta_x = random.Random().randrange(start=delta[1][0], stop=delta[1][2]) random_delta_y = random.Random().randrange(start=delta[1][1], stop=delta[1][3]) break logger.log( "match and click template = {}, source = {}, position = ({}, {}), random_delta = ({}, {})" .format(template, source, x, y, random_delta_x, random_delta_y)) click(x + random_delta_x, y + random_delta_y) return True return False
def match_template(template, source, resize=True, match_threshold=0.9): global special_match_threshold if template in special_match_threshold: match_threshold = special_match_threshold[template] template_img = cv.imread(template) # Mac的Retina屏幕截取的图片会出现分辨率不匹配的问题,需要压缩才能正常匹配 if resize: template_img = cv.resize(template_img, (0, 0), fx=0.5, fy=0.5) source_img = cv.imread(source) match_result = cv.matchTemplate(source_img, template_img, cv.TM_CCOEFF_NORMED) min_val, max_val, min_loc, max_loc = cv.minMaxLoc(match_result) template_name = template.replace(config.template_img_path, "") logger.log("match {} in {} result is {}, {}".format( logger.resource_path_to_name(template_name), logger.temp_path_to_name(source), (min_val, max_val, min_loc, max_loc), match_threshold)) if max_val > match_threshold and config.currentDebugLevel.value > config.DebugLevel.JUST_LOG.value: corner_loc = (max_loc[0] + template_img.shape[1], max_loc[1] + template_img.shape[0]) center_spot = (max_loc[0] + int(template_img.shape[1] / 2), max_loc[1] + int(template_img.shape[0] / 2)) cv.circle(source_img, center_spot, 10, (0, 255, 255), -1) cv.rectangle(source_img, max_loc, corner_loc, (0, 0, 255), 3) if config.currentDebugLevel.value > config.DebugLevel.SAVE_IMG.value: cv.imshow("MatchResult", source_img) cv.waitKey(2000) cv.imwrite(source.replace(".png", "_match.png"), source_img) return max_val, max_loc, (max_loc[0] + template_img.shape[1], max_loc[1] + template_img.shape[0])
def accept(self, capture): ac = global_status.is_in_battle if self.turn_num != -1: logger.log( "skill check turn, target is {} and current is {}".format( self.turn_num, global_status.turn_num)) ac = ac and (self.turn_num == global_status.turn_num) if self.accept_extra is not None: ac = ac and self.accept_extra(capture) logger.log("skill task accept result is {}".format(ac)) return ac
def check(self, capture, index): # 这个数值是试出来的,反正能用 threshold = 40 top = 518 bottom = 524 np_bar_width = 86 left = 96 * (index + 1) + 100 * index right = left + np_bar_width crop = capture[top:bottom, left:right] result = numpy.mean(crop) > threshold logger.log("check np at {}, result is {}".format(index, result)) global_status.hougu_status[index] = result return result
def on_execute(self, capture): skill_used = global_status.skill_history.get(self.template, {}) logger.log("skill history for {} is {}".format( logger.resource_path_to_name(self.template), skill_used)) can_use_skill = False for skill in self.skill_index: if not skill_used.get(skill, False): can_use_skill = True break if not can_use_skill: return wait_for(resources.battle_attack_button) skill_position = global_status.skill_position_cache.get( self.template, ()) if len(skill_position) == 0: logger.log( "not find cached skill position, start match in capture") local_count = 0 while local_count < 5: local_count = local_count + 1 capture = ui_util.get_new_capture() max_val, tl_loc, br_loc = cv_util.match_template( self.template, capture) if max_val > 0.6: left, top, right, bottom = tl_loc[0], tl_loc[1], br_loc[ 0], br_loc[1] skill_position = (left, top, right, bottom) global_status.skill_position_cache[ self.template] = skill_position logger.log("find skill template ,position is {}".format( skill_position)) break else: wait_for(self.template) if len(skill_position) == 0: logger.log("not find skill position, return") return left, top, right, bottom = skill_position[0], skill_position[ 1], skill_position[2], skill_position[3] width = right - left item_width = width / 3 center_y = (top + bottom) / 2 for skill in self.skill_index: if not skill_used.get(skill, False): wait_for(resources.battle_attack_button) x = left + item_width * (skill - 1) + item_width / 2 random_x = random.Random().randrange(start=-10, stop=10) random_y = random.Random().randrange(start=-10, stop=10) logger.log_with_echo( "click skill {}, original position is ({} ,{}), random_delta = ({}, {})" .format(logger.resource_path_to_name(self.template), x, center_y, random_x, random_y)) ui_util.click(x + random_x, center_y + random_y) skill_used = global_status.skill_history.get(self.template, {}) skill_used[skill] = True global_status.skill_history[self.template] = skill_used time.sleep(random.randrange(2, 3))
def execute(self, capture): super().execute(capture) logger.log( "click start battle task ,before reset status ,skill history is {}" .format(global_status.skill_history)) global_status.is_in_battle = True global_status.turn_num = 1 global_status.skill_history = {} global_status.skill_history.clear() # global_status.skill_position_cache = {} global_status.hougu_status = [False, False, False] global_status.loop_number = global_status.loop_number + 1 logger.log( "click start battle task ,after reset status ,skill history is {}". format(global_status.skill_history)) logger.log_with_echo("start new battle {}".format( global_status.loop_number))
def wait_for(template, step=3, threshold=0.9, max_count=5, extra_resources=None): if extra_resources is None: extra_resources = [] count = 0 while not ui_util.get_new_capture_and_match( template, threshold=threshold, remove_after_match=True): for extra in extra_resources: if ui_util.get_new_capture_and_match(extra, threshold=threshold, remove_after_match=True): return time.sleep(step) count = count + 1 if count > max_count: logger.log("wait for {} has run for {} times, break out".format( logger.resource_path_to_name(template), count)) break