Почему pyautogui.locateOnScreen() находит мое изображение только на первой итерации цикла?Python

Программы на Python
Ответить
Anonymous
 Почему pyautogui.locateOnScreen() находит мое изображение только на первой итерации цикла?

Сообщение Anonymous »

Я пытаюсь создать сценарий автоматического кликера для старой игры, в котором игрок собирает статистику при создании персонажа. Я хочу прочитать экран игры на наличие минимального балла и, если он не найден, нажать «перевернуть», а затем снова запустить проверку. У меня в каталоге IDE сохранены снимки экрана с минимальным счетом (8 цифр) и кнопкой повторного просмотра с экрана выбора персонажа. Идея состоит в том, чтобы использовать функцию pyautogui.locateOnScreen() для проверки минимального балла в области экрана, которую я определяю путем сопоставления с сохраненным изображением минимального балла. Если он недостаточно высок, курсор должен нажать кнопку повторного прокрутки, которая расположена так же, как при проверке снимка экрана с кнопкой повторного прокрутки. На данный момент у меня есть следующий код:

Код: Выделить всё

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)
Когда я запускаю код, окно игры обнаруживается и правильно становится на передний план. Если случайный бросок, с которого начинается игра, удовлетворяет критерию поиска (выпавший в 80-х годах), сценарий ведет себя так, как ожидалось (печатает сообщение «выпало в 80-х» и нажимает на счет). Однако, если стартовый счет не удовлетворяет критерию поиска, сценарий постоянно печатает «счет не в 80-х», «перебрасывается» и нажимает кнопку переброса, даже если новый счет после переброса удовлетворяет требованиям. Похоже, что pyautogui.locateOnScreen() ведет себя так, как ожидалось, на первой итерации цикла while True, но неожиданно на последующих итерациях. Я не понимаю, почему, и отладка проблематична, потому что игра сворачивается, если я нажимаю на любой другой экран, даже на других мониторах.
Я прочитал несколько сообщений, в которых говорилось, что функция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
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Python»