Код: Выделить всё
import win32gui
import win32con
import sys
import pyautogui
import time
game_window = "Baldur's Gate - Enhanced Edition - v2.6.6.0"
#find game window and make foreground - otherwise exit script
def find_window_and_foreground(target):
hwnd = win32gui.FindWindow(None, target)
if hwnd > 0:
win32gui.ShowWindow(hwnd, win32con.SW_RESTORE)
win32gui.SetForegroundWindow(hwnd)
print("game set to foreground")
else:
print("Baldur's Gate not running - exiting program")
sys.exit()
time.sleep(1)
#pixel location of leading digit in total score on screen in game - x,y,width,height
search_range = (977,1108,108,40)
#look for a minimum score of 80 and return true otherwise print low roll message and return false
#8-10s.png is a clipped screenshot of an 8 as the leading digit in total score in-game
def check_score():
try:
location_of_score = pyautogui.locateOnScreen('8-10s.png', confidence=0.8, region=search_range)
pyautogui.click(location_of_score)#just for testing
return True
except pyautogui.ImageNotFoundException:
print('score is not in the 80s')
return False
find_window_and_foreground(game_window)
#look for reroll button in game - exit if not found
try:
reroll_location = pyautogui.locateOnScreen('reroll.png', confidence=0.8)
except pyautogui.ImageNotFoundException:
print("reroll button not found - exiting program")
sys.exit()
while True:
if check_score():
print('rolled in the 80s')
sys.exit()
else:
pyautogui.click(reroll_location)
print('rerolled')
time.sleep(2)
Я прочитал несколько сообщений, в которых говорилось, что функцияlocateOnScreen() может занять некоторое время (я думаю, в документации указано 2-5 секунд или около того), но я не думаю, что это причина неожиданного поведения, потому что искомое изображение и поле поиска довольно малы, и у меня есть 2 вторая задержка в скрипте как есть (я также тестировал ее до 5 секунд с таким же поведением). Кроме того, как я уже сказал выше, если начальное значение общего балла превышает 80, программа работает правильно (это также тот случай, если я вручную повторно увеличиваю балл до 80 или выше, а затем запускаю скрипт).
В других сообщениях оlocateOnScreen() также упоминается игра со значением достоверности в качестве аргумента. Я установил значение 0,8 и получил приличные результаты. Иногда мне все еще не хватает кнопки перемотки, но после нескольких попыток она работает правильно. Я также не думаю, что это является причиной наблюдаемого поведения, поскольку результаты общего балла при первом проходе цикла while True близки к 100 %, в то время как последующие проходы никогда не давали совпадений, даже после нескольких минут повтора.
Действительно кажется, что я могу получить значение True для check_score() только при первом проходе цикла while True, в то время как каждая последующая итерация дает False возвращаемое значение. Мои познания в программировании очень ограничены, но я смутно припоминаю, что при чтении входных данных на Java было хорошей практикой создавать новые экземпляры сканера, потому что он использовал буфер, который мог дать неожиданные результаты, если бы содержимое не было «сброшено» путем создания нового экземпляра. Здесь происходит что-то подобное?
Будем благодарны за любую помощь.
Окружающая среда:
ОС Windows 10 22H2, сборка 19045.6466
python 3.9.13
PyCharm 2022.3.3 (Community Edition) Сборка #PC-223.8836.43
Помимо импортированных пакетов, аргумент доверия для pyautogui.locateOnScreen() использует opencv-python.




Обновление. После небольшого дополнительного тестирования выяснилось, что проблема не в том, что изображение обнаруживается только при первом проходе цикла while True. Если первоначальный счет (тот, который присутствует в игре, когда я запускаю скрипт) не соответствует требованиям (8 в качестве ведущей цифры), но повторный бросок (в скрипте) соответствует требованию, то alt + Tab выходит за пределы игрового экрана и возвращается обратно до того, как выполнится time.sleep(2), чтобы найти изображение. Это заставило меня подумать, что экран игры может быть отменен в качестве окна переднего плана для целей снимка экрана, который puautogui.locateOnScreen() использует для проверки изображений (хотя щелчки для повторного прокрутки по-прежнему работают так, как будто окно игры является передним планом). Поэтому я попробовал добавить find_window_and_foreground() в качестве первой строки в цикле while True, но поведение такое же, как и раньше.
Обновление 2: похоже, что функция pyautogui.locateOnScreen() не делает надежный снимок экрана окна игры. Я добавил вызов pyautogui.screenshot() в начале check_score() и прямо перед назначением reroll_location, чтобы посмотреть, что может произойти. Когда скрипт не мог найти кнопку перемотки, соответствующий снимок экрана представлял собой в основном черный экран, но с некоторыми значками, казалось бы, слитыми вместе из других окон, в то время как пропущенные поисковые запросы с общим баллом 8 (когда на самом деле присутствовала 8) соответствовали снимку экрана моего рабочего стола. Я действительно не уверен, почемуlocateOnScreen() ведет себя таким образом, поскольку я выдвигаю на передний план окно игры в начале сценария, щелчки повторного прокрутки работают правильно, и никакое другое окно, похоже, не становится на передний план. Возможно, это как-то связано с наличием двух мониторов (я запускаю скрипт из IDE на другом экране)?
Обновление 3: отключение наложения GOG (я использую версию игры GOG), по-видимому, устраняет проблему, когда скриншоты, которые использует методlocateOnScreen(), представляют собой черные/несколько экранов, объединенных вместе, а не экран игры. Однако, судя по снимкам экрана, созданным вызовами pyautogui.screenshot(), упомянутыми в обновлении выше, LocationOnScreen() использует снимок экрана из первого прохода цикла while True во всех последующих циклах. Другими словами, скриншоты для первой проверки кнопки повторного броска и первой проверки высокого балла используются повторно или копируются снова и снова, и именно поэтому я не могу получить никаких положительных совпадений, если первоначальный балл не соответствует критерию.
Подробнее здесь: https://stackoverflow.com/questions/798 ... eration-of
Мобильная версия