ソースを参照

add health bar check to dungeon runner

Richard Köhl 1 年間 前
コミット
0368e4d585

+ 78 - 11
dungeon.py

@@ -1,26 +1,69 @@
 import cv2
 import time
+import numpy as np
 from helper import (
     tap,
     look_for_templates,
     find_template,
+    first_template,
     capture_current_screen,
+    get_current_screen,
 )
 
 # templates
 templates = {
     "to_battle": cv2.imread("templates/dungeon/to_battle2.png"),
     "attack": cv2.imread("templates/dungeon/attack.png"),
-    "water": cv2.imread("templates/dungeon/water.png"),
-    "mixed": cv2.imread("templates/dungeon/mixed.png"),
-    "earth": cv2.imread("templates/dungeon/earth.png"),
     "auto_battle": cv2.imread("templates/dungeon/auto_battle.png"),
     "ok": cv2.imread("templates/dungeon/ok.png"),
     "lock": cv2.imread("templates/dungeon/lock.png"),
     "collect": cv2.imread("templates/dungeon/collect.png"),
 }
 
+tpl_mixed = cv2.imread("templates/dungeon/mixed.png")
+tpl_water = cv2.imread("templates/dungeon/water.png")
+tpl_earth = cv2.imread("templates/dungeon/earth.png")
+tpl_angus = cv2.imread("templates/dungeon/angus.png")
+tpl_moloch = cv2.imread("templates/dungeon/moloch.png")
+tpl_angus2 = cv2.imread("templates/dungeon/angus2.png")
+tpl_moloch2 = cv2.imread("templates/dungeon/moloch2.png")
+
+
+def low_health(element, name):
+    left = element[0] - 113
+    right = element[0] + 108
+    top = element[1] + 158
+    bottom = top + 11
+
+    screen = read_screen()
+
+    health_bar = screen[top:bottom, left:right]
+    cv2.imwrite("test/health_bar.png", health_bar)
+
+    health_bar_hsv = cv2.cvtColor(health_bar, cv2.COLOR_BGR2HSV)
+    green_lower = np.array([40, 40, 40])  # Lower end of green in HSV
+    green_upper = np.array([80, 255, 255])  # Upper end of green in HSV
+
+    mask = cv2.inRange(health_bar_hsv, green_lower, green_upper)
+
+    total_length = mask.shape[1]
+    current_length = total_length - np.argmax(np.flip(mask[0]) > 0)
+    health_percentage = (current_length / total_length) * 100
+
+    print(f"Remaining Health ({name}): {health_percentage:.2f}%")
+
+    return health_percentage < 60
+
+
+def read_screen():
+    data = get_current_screen()
+    image_data = np.frombuffer(data, dtype=np.uint8)
+
+    return cv2.imdecode(image_data, cv2.IMREAD_COLOR)
+
+
 print("watching the screen...")
+is_mixed = False
 while True:
     time.sleep(0.5)  # Polling interval
     capture_current_screen()
@@ -28,15 +71,39 @@ while True:
     name, locations = look_for_templates(templates)
     if name is not None:
         if name in ["to_battle", "auto_battle", "ok", "lock", "collect"]:
-            tap(*locations[0])
             if name in ["auto_battle"]:
-                time.sleep(0.5)
+                if is_mixed:
+                    moloch = first_template(tpl_moloch)
+                    if moloch and moloch[1] < 1000 and low_health(moloch, "moloch"):
+                        angus = first_template(tpl_angus2)
+                        tap(angus)
+                        time.sleep(0.5)
+                        tap(angus[0] + 500, angus[1])
+                    else:
+                        angus = first_template(tpl_angus)
+                        if angus and angus[1] < 1000 and low_health(angus, "angus"):
+                            moloch = first_template(tpl_moloch2)
+                            tap(moloch)
+                            time.sleep(0.5)
+                            tap(moloch[0] - 500, moloch[1])
+                    time.sleep(0.5)
+            tap(*locations[0])
+            if name in ["auto_battle", "ok"]:
+                time.sleep(1.5)
         if name == "attack" and len(locations) == 1:
+            element = first_template(tpl_mixed)
+            is_mixed = element is not None
             tap(*locations[0])
         if name == "attack" and len(locations) == 2:
-            element = find_template(templates["mixed"])
-            if len(element) == 0:
-                element = find_template(templates["water"])
-                if len(element) == 0:
-                    element = find_template(templates["earth"])
-            tap(element[0][0], locations[0][1])
+            element = first_template(tpl_mixed)
+            if element:
+                is_mixed = True
+            else:
+                is_mixed = False
+                element = first_template(tpl_water)
+                if element is None:
+                    element = first_template(tpl_earth)
+
+            tap(element[0], locations[0][1])
+
+    print("...")

+ 43 - 7
helper.py

@@ -4,6 +4,14 @@ from io import BytesIO
 from PIL import Image
 from ppadb.client import Client as AdbClient
 
+with_cuda = 0
+if cv2.cuda.getCudaEnabledDeviceCount() > 0:
+    print("CUDA is available")
+    with_cuda = 1
+else:
+    print("CUDA is not available")
+    with_cuda = 0
+
 
 def get_current_screen():
     return current_screen
@@ -32,6 +40,8 @@ def tap(x, y=None):
     # Check if x is a string
     elif isinstance(x, str):
         location = x
+    elif isinstance(x, tuple):
+        location = f"{x[0]} {x[1]}"
     else:
         raise TypeError("x must be either an int or a string")
 
@@ -63,17 +73,43 @@ def look_for_templates(templates):
     return None, None
 
 
+def first_template(template_image):
+    result = find_template(template_image)
+    if len(result) > 0:
+        return result[0]
+
+    return None
+
+
 def find_template(template_image):
-    target_image = Image.open(BytesIO(get_current_screen()))
+    if with_cuda == 1:
+        # Ensure the images are in the correct format (BGR for OpenCV)
+        target_image = capture_current_screen()
+
+        # Upload images to GPU
+        target_image_gpu = cv2.cuda_GpuMat()
+        template_image_gpu = cv2.cuda_GpuMat()
+
+        target_image_gpu.upload(target_image)
+        template_image_gpu.upload(template_image)
+
+        # Perform template matching on the GPU
+        result_gpu = cv2.cuda.createTemplateMatching(cv2.CV_8UC3, cv2.TM_CCOEFF_NORMED)
+        result = result_gpu.match(target_image_gpu, template_image_gpu)
+
+        # Download result from GPU to CPU
+        result = result.download()
+    else:
+        target_image = Image.open(BytesIO(get_current_screen()))
 
-    # 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)
+        # 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)
 
-    h, w = template_image.shape[:-1]
+        h, w = template_image.shape[:-1]
 
-    # Template matching
-    result = cv2.matchTemplate(target_image, template_image, cv2.TM_CCOEFF_NORMED)
+        # 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

BIN
templates/dungeon/angus.png


BIN
templates/dungeon/angus2.png


BIN
templates/dungeon/moloch.png


BIN
templates/dungeon/moloch2.png