import cv2 import time import datetime import numpy as np from PIL import Image from io import BytesIO from ppadb.client import Client as AdbClient client = AdbClient(host="127.0.0.1", port=5037) device = client.device("192.168.178.32:5555") # template positions close_sub_fights = cv2.imread('templates/close_sub_fights.jpg') close_fight = cv2.imread('templates/close_fight.jpg') fight_button = cv2.imread('templates/i.jpg') end_of_log = cv2.imread('templates/end_of_log.jpg') # cursor positions fight_scroll_top = "2494 626" titan_fight = "1400 860" damage_taken = "450 850" close_details = "2175 450" close_titan_fight = "2650 570" def non_max_suppression(boxes, overlapThresh): if len(boxes) == 0: return [] # Convert to float boxes = np.array(boxes, dtype="float") # Initialize the list of picked indexes pick = [] # Grab the coordinates of the bounding boxes x1 = boxes[:,0] y1 = boxes[:,1] x2 = boxes[:,2] y2 = boxes[:,3] # Compute the area of the bounding boxes and sort by bottom-right y-coordinate area = (x2 - x1 + 1) * (y2 - y1 + 1) idxs = np.argsort(y2) # Keep looping while some indexes still remain in the indexes list while len(idxs) > 0: # Grab the last index in the indexes list and add the index value to the list of picked indexes last = len(idxs) - 1 i = idxs[last] pick.append(i) # Find the largest (x, y) coordinates for the start of the bounding box and the smallest (x, y) # coordinates for the end of the bounding box xx1 = np.maximum(x1[i], x1[idxs[:last]]) yy1 = np.maximum(y1[i], y1[idxs[:last]]) xx2 = np.minimum(x2[i], x2[idxs[:last]]) yy2 = np.minimum(y2[i], y2[idxs[:last]]) # Compute the width and height of the bounding box w = np.maximum(0, xx2 - xx1 + 1) h = np.maximum(0, yy2 - yy1 + 1) # Compute the ratio of overlap overlap = (w * h) / area[idxs[:last]] # Delete all indexes from the index list that have overlap greater than the threshold idxs = np.delete(idxs, np.concatenate(([last], np.where(overlap > overlapThresh)[0]))) # Return only the bounding boxes that were picked return boxes[pick].astype("int") def screen_has_changed(prev_screenshot, threshold=0.01): # Take a new screenshot current_screenshot = device.screencap() # Convert to NumPy arrays prev_img = np.frombuffer(prev_screenshot, dtype=np.uint8) current_img = np.frombuffer(current_screenshot, dtype=np.uint8) # Load images prev_img = cv2.imdecode(prev_img, cv2.IMREAD_COLOR) current_img = cv2.imdecode(current_img, cv2.IMREAD_COLOR) # Calculate absolute difference diff = cv2.absdiff(prev_img, current_img) non_zero_count = np.count_nonzero(diff) # print(f"diff: {non_zero_count} > {threshold * diff.size} = {non_zero_count > threshold * diff.size}") # Check if the difference is greater than the threshold return non_zero_count > threshold * diff.size def save_screenshot(): # Take a screenshot result = device.screencap() timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S") filename = f"fights/{timestamp}.png" # Save the screenshot to a file with open(filename, "wb") as fp: fp.write(result) time.sleep(0.5) def wait_for_screen_change(): # Usage example prev_screenshot = device.screencap() while not screen_has_changed(prev_screenshot): time.sleep(0.1) # Polling interval def tap(location): device.shell(f"input tap {location}") time.sleep(1) def swipe(start, end): device.shell(f"input swipe {start} {end} 1000") time.sleep(0.5) def tap_button(template): button = find_templates(template) if len(button) == 0: return tap(f"{button[0][0]} {button[0][1]}") def is_end_of_log(template): templates = find_templates(template) result = len(templates) > 0 if result: print(templates) print("reached end of guild war log!") return result def find_templates(template_image): screenshot = device.screencap() target_image = Image.open(BytesIO(screenshot)) # Convert the image to a NumPy array and then to BGR format (which OpenCV uses) target_image = np.array(target_image) target_image = cv2.cvtColor(target_image, cv2.COLOR_RGB2BGR) w, h = template_image.shape[:-1] # Template matching result = cv2.matchTemplate(target_image, template_image, cv2.TM_CCOEFF_NORMED) # Define a threshold threshold = 0.9 # Adjust this threshold based on your requirements # Finding all locations where match exceeds threshold locations = np.where(result >= threshold) locations = list(zip(*locations[::-1])) # Create list of rectangles rectangles = [(*loc, loc[0] + w, loc[1] + h) for loc in locations] # Apply non-maximum suppression to remove overlaps rectangles = non_max_suppression(rectangles, 0.3) # Initialize an empty list to store coordinates coordinates = [] for (startX, startY, endX, endY) in rectangles: # Calculate the center coordinates centerX = round(startX + (endX - startX) / 2) centerY = round(startY + (endY - startY) / 2) # Append the coordinate pair to the list coordinates.append((centerX, centerY)) return coordinates def find_max_y_pair(coordinates): # find the coordinate pair with the maximum y value result = max(coordinates, key=lambda x: x[1]) return f"{result[0]} {result[1]}" def take_fight_screenshots(): save_screenshot() tap(damage_taken) save_screenshot() tap_button(close_fight) def process_war_log(): buttons = find_templates(fight_button) # process all found buttons for pair in buttons: tap(f"{pair[0]} {pair[1]}") sub_buttons = find_templates(fight_button) if (len(sub_buttons) == 0): take_fight_screenshots() else: for pair2 in sub_buttons: tap(f"{pair2[0]} {pair2[1]}") take_fight_screenshots() tap_button(close_sub_fights) find_max_y_pair(buttons) swipe(find_max_y_pair(buttons), fight_scroll_top) # start while True: process_war_log(); if is_end_of_log(end_of_log): break;