Как оптимизировать бота для игры с падающими звездами?
Есть мини-игра, для которой я захотел сделать бота, суть в том, что сверху падает много зеленых звезд, которые нужно нажимать, что бы получить очки, окно с игрой выглядит так[1
Так же как можно заметить сверху падают бомбы, так что просто сделать кликер не получится. Я использовал opencv, pyautogui.
import cv2
import pyautogui as pag
import numpy as np
from PIL import ImageGrab
import threading
import concurrent.futures
import keyboard
star_threshold = 0.3
pag.FAILSAFE = True
start_hotkey = 'ctrl+shift+s'
stop_hotkey = 'ctrl+shift+s'
bigStar1 = "C:/Users/steam/IdeaProjects/BlumBot/BigStarP.jpg"
r_bs1 = cv2.imread('bigStarP.jpg')
bigStarP = cv2.cvtColor(r_bs1, cv2.COLOR_RGB2GRAY)
bigStar2 = "C:/Users/steam/IdeaProjects/BlumBot/BigStarN.jpg"
r_bs2 = cv2.imread('bigStarN.jpg')
bigStarN = cv2.cvtColor(r_bs2, cv2.COLOR_RGB2GRAY)
mediumStar1 = "C:/Users/steam/IdeaProjects/BlumBot/mediumStarP.jpg"
r_ms1 = cv2.imread('mediumStarP.jpg')
mediumStarP = cv2.cvtColor(r_ms1, cv2.COLOR_RGB2GRAY)
mediumStar2 = "C:/Users/steam/IdeaProjects/BlumBot/mediumStarN.jpg"
r_ms2 = cv2.imread('mediumStarN.jpg')
mediumStarN = cv2.cvtColor(r_ms2, cv2.COLOR_RGB2GRAY)
reallysmallstar1 = "C:/Users/steam/IdeaProjects/BlumBot/reallysmallstarP.jpg"
r_rss1 = cv2.imread('reallysmallstarP.jpg')
reallysmallstarP = cv2.cvtColor(r_rss1, cv2.COLOR_RGB2GRAY)
reallysmallstar2 = "C:/Users/steam/IdeaProjects/BlumBot/reallysmallstarN.jpg"
r_rss2 = cv2.imread('reallysmallstarN.jpg')
reallysmallstarN = cv2.cvtColor(r_rss2, cv2.COLOR_RGB2GRAY)
smallStar1 = "C:/Users/steam/IdeaProjects/BlumBot/smallStarP.jpg"
r_ss1 = cv2.imread('smallStarP.jpg')
smallStarP = cv2.cvtColor(r_ss1, cv2.COLOR_RGB2GRAY)
smallStar2 = "C:/Users/steam/IdeaProjects/BlumBot/smallStarN.jpg"
r_ss2 = cv2.imread('smallStarN.jpg')
smallStarN = cv2.cvtColor(r_ss2, cv2.COLOR_RGB2GRAY)
star1 = "C:/Users/steam/IdeaProjects/BlumBot/1.jpg"
st1 = cv2.imread('1.jpg')
star1a = cv2.cvtColor(st1, cv2.COLOR_RGB2GRAY)
star2 = "C:/Users/steam/IdeaProjects/BlumBot/2.jpg"
st2 = cv2.imread('2.jpg')
star2a = cv2.cvtColor(st2, cv2.COLOR_RGB2GRAY)
star3 = "C:/Users/steam/IdeaProjects/BlumBot/3.jpg"
st3 = cv2.imread('3.jpg')
star3a = cv2.cvtColor(st3, cv2.COLOR_RGB2GRAY)
star4 = "C:/Users/steam/IdeaProjects/BlumBot/4.jpg"
st4 = cv2.imread('4.jpg')
star4a = cv2.cvtColor(st4, cv2.COLOR_RGB2GRAY)
star5 = "C:/Users/steam/IdeaProjects/BlumBot/5.jpg"
st5 = cv2.imread('5.jpg')
star5a = cv2.cvtColor(st5, cv2.COLOR_RGB2GRAY)
star6 = "C:/Users/steam/IdeaProjects/BlumBot/6.jpg"
st6 = cv2.imread('6.jpg')
star6a = cv2.cvtColor(st6, cv2.COLOR_RGB2GRAY)
star7 = "C:/Users/steam/IdeaProjects/BlumBot/7.jpg"
st7 = cv2.imread('7.jpg')
star7a = cv2.cvtColor(st7, cv2.COLOR_RGB2GRAY)
star8 = "C:/Users/steam/IdeaProjects/BlumBot/8.jpg"
st8 = cv2.imread('8.jpg')
star8a = cv2.cvtColor(st8, cv2.COLOR_RGB2GRAY)
templates = [bigStarP, bigStarN, mediumStarP, mediumStarN, smallStarP, smallStarN, reallysmallstarP,
reallysmallstarN, star1a, star2a, star3a, star4a, star5a, star6a, star7a, star8a]
keyboard.wait('space')
def find_object(template):
while True:
try:
screenshot = ImageGrab.grab(bbox=(777, 238, 1140, 802))
screenshot.save('popka.png')
readed = cv2.imread('popka.png')
screenshot_ready = cv2.cvtColor(readed, cv2.COLOR_RGB2GRAY)
img_star = template
res = cv2.matchTemplate(screenshot_ready, img_star, cv2.TM_SQDIFF_NORMED)
loc_of = np.where(res >= star_threshold)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)
print(max_val)
print(min_val)
if min_val < star_threshold:
print(max_val)
try:
center_x = min_loc[0] + img_star.shape[1] // 2 + 777
center_y = min_loc[1] + img_star.shape[0] // 2 + 238
pag.leftClick(center_x, center_y)
except:
pass
except ValueError as e:
print(f'{e}')
# Создаем пул потоков
with concurrent.futures.ThreadPoolExecutor(max_workers=len(templates)) as executor:
# Запускаем все потоки в пуле
executor.map(find_object, templates)
keyboard.wait('space')
print('popka')
Так выглядит весь код со всеми шаблонами etc И проблема в том, что бы я не пробывал, я не могу собрать более ~100 звездочек, хотя максимум около 250 Я пробывал все что в моих силах, я делал кеширование координат, что бы не тыкать на одну и ту же звезду(на скриншоте например) Я добавил многопоточность, я менял методы сравнения cv2.matchTemplate Я добавлял меньше темплейтов, больше. Ничего не помогает вообще, каждый запуск кода это стабильно 100 звезд, чего бы я в коде там не менял. Прошу помогите я устал(
Ответы (1 шт):
Первое что я заметил, это то что Вы сохраняете скриншот в файл, а потом читаете его - это нагружает систему
frame = np.array(pyautogui.screenshot(region=(777, 238, 1140, 802))) # и вообще лучше дать возможность детектить нужно место с помощью средств самого pyautogui
screen = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
Тут Вы сразу можете получить нужное для Вас изображение, не тратя ресурсов на сохранение и загрузку файла в ОЗУ
Так же бы посотоветовал убрать print
, это так же может отнять драгоценные ресурсы.
Так же предлагаю отказаться от жестких рамок для скриншота (ImageGrab.grab(bbox=(777, 238, 1140, 802))
), отдав предпочтение такому варианту:
window = gw.getWindowsWithTitle("TelegramDesktop")[0]
frame = np.array(pyautogui.screenshot(region=(window.left, window.top, window.width, window.height)))
screen = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)