
Olá pessoal, sou um usuário feliz do sistema operacional GNU / Linux e, como muitas pessoas sabem, há muito menos brinquedos indo para o Linux sem danças adicionais com um pandeiro do que no Windows.
E menos jogos no gênero MMORPG.
No entanto, cerca de meio ano ou um ano atrás, descobri que eles haviam portado o jogo Albion Online para o Linux.
O jogo é muito divertido, mas leva bastante tempo. E para não desperdiçar minhas preciosas horas de vida em vão, decidi escrever um bot. Quem me cultivará recursos enquanto eu cuido dos meus negócios.
O jogo tem muitos tipos de artesanato, você pode cortar madeira, cavar pedras e até cultivar jardins, mas minha escolha foi feita em favor da pesca.
Portanto, a essência da pesca on-line em Albion é simples, pegue uma vara de pescar, vá para o lago, mantenha pressionado o botão para jogar a isca, aguarde um pouco.

Ao bicar, você deve novamente pressionar os botões e jogar um mini-jogo.
Aqui você precisará puxar alternadamente e não puxar a vara de pescar, dependendo dos movimentos da bóia. O flutuador sempre se move aleatoriamente, com diferentes seqüências e velocidades. E se você fizer tudo certo e a bóia não for além da zona permitida, você irá pescar.
Então, automatizaremos todo esse negócio. Por meio da linguagem de computador python. Decidi começar do mais difícil, a partir do momento em que o jogo começa com um carro alegórico. Aqui, novamente, minha
biblioteca de visão por computador
OpenCV favorita veio em meu socorro. Ao iniciá-lo, podemos detectar objetos, por exemplo, em imagens. No entanto, a própria biblioteca não sabe exatamente o que precisamos descobrir. Obviamente, existem muitos padrões em que vários objetos são apresentados para defini-los. No entanto, definitivamente não há carros alegóricos para o Albion Online.
Mas nesta biblioteca há uma maravilhosa função de pesquisa para um determinado modelo. E como modelo, tirei uma captura de tela do nosso carro alegórico.

E, como vemos, tudo foi encontrado perfeitamente na imagem.
E a diferença entre a imagem e o vídeo streaming não é grande, porque na verdade é apenas um fluxo de imagens com uma velocidade muito rápida e algumas linhas de código. E agora já podemos encontrar a flutuação no streaming de vídeo.
Códigoimport numpy as np import cv2 from mss.linux import MSS as mss from PIL import Image import time import pyautogui as pg import cv2 import mss import numpy template = cv2.imread("2019-07-02_06-55_1.png", cv2.IMREAD_GRAYSCALE) w, h = template.shape[::-1] with mss.mss() as sct: monitor = {"top": 40, "left": 0, "width": 800, "height": 640} while "Screen capturing": last_time = time.time() img = numpy.array(sct.grab(monitor)) cv2.imshow("OpenCV/Numpy normal", img) print("fps: {}".format(1 / (time.time() - last_time))) gray_frame = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) res = cv2.matchTemplate(gray_frame, template, cv2.TM_CCOEFF_NORMED) loc = np.where(res >= 0.7) for pt in zip(*loc[::-1]): cv2.rectangle(img, pt, (pt[0] + w, pt[1] + h), (0, 255, 0), 3) cv2.imshow("Frame", img) key = cv2.waitKey(1) if cv2.waitKey(25) & 0xFF == ord("q"): cv2.destroyAllWindows() break
Nós vamos além. O flutuador em si se move para frente e para trás e também precisamos movê-lo pressionando o botão do mouse.
E, portanto, precisamos de suas coordenadas. E para isso, essas linhas nos ajudam.
for p in img: pts = (pt[0],pt[1]) x = (pt[0]) y = (pt[1]) print (x) cv2.circle(template,pts,5,(200,0,0),2) cv2.putText(img, "%d-%d" % (x,y), (x+10,y-10), cv2.FONT_HERSHEY_SIMPLEX, 1, color_yellow, 2)
Depois, apenas usamos a biblioteca
PyAutoGUI , que prende o botão do mouse e o pressiona com uma certa frequência.
if 100 < x < 500: pyautogui.mouseDown(button='left') time.sleep(1) pyautogui.mouseUp(button='left') x = 0
E o mini-jogo em si é vencido com sucesso.

Colocamos tudo em uma função e deixamos por enquanto.
Em seguida, retornamos à peça original, onde devemos monitorar o flutuador.
É tudo um pouco diferente, por exemplo, podemos determinar onde o flutuador será lançado e tentar analisar essa parte da tela quanto à presença do flutuador. No entanto, a bóia lançada na água aparece em ângulos diferentes e oscila constantemente.
Nesse caso, usaremos esse método um pouco diferente. Sua essência é que analisamos, digamos a diferença de pixels dentro do fragmento rastreado. Que, se não houver flutuação, se aproxima de zero.
Como resultado, foi encontrado o valor ideal no qual, com o desaparecimento do flutuador, podemos executar ações.
Código def screen_record(): sct = mss.mss() last_time = time.time() while(True): img = sct.grab(mon) print('loop took {} seconds'.format(time.time() - last_time)) last_time = time.time() img = np.array(img) processed_image = process_image(img) mean = np.mean(processed_image) print('mean = ', mean) if mean <= float(0.11): print('SSSSSSSS ') pyautogui.click(button='left') break return else: time.sleep(0.01) continue return if cv2.waitKey(25) & 0xFF == ord('q'): cv2.destroyAllWindows() break
E nós os produzimos, ou seja, clique no botão do mouse. Também colocamos isso na função.
E finalmente, em conclusão, simplesmente escrevemos um script em que, em um loop infinito, jogamos uma vara de pescar e executamos a primeira e a segunda funções alternadamente.
while "": time.sleep(1) pyautogui.moveTo(431,175,duration=1) pyautogui.mouseDown(button='left') pyautogui.moveTo(450.200,duration=1) pyautogui.mouseUp(button='left') time.sleep(2) screen_record() time.sleep(0.01) ss()
Aqui está uma instrução em vídeo completa e um exemplo do trabalho deste bot:
Na verdade, existem algumas nuances nas quais você precisa se misturar com números, pois esses números são selecionados para o meu monitor, localização, personagem e equipamento. Mas acho que para um pythonist competente isso não será um problema.
O script inteiro:
Código import numpy as np import cv2 from mss.linux import MSS as mss from PIL import Image import time import pyautogui as pg import imutils import mss import numpy import pyautogui template = cv2.imread("2019-07-02_06-55_1.png", cv2.IMREAD_GRAYSCALE) w, h = template.shape[::-1] color_yellow = (0,255,255) mon = {'top': 80, 'left': 350, 'width': 100, 'height': 100} def process_image(original_image): processed_image = cv2.cvtColor(original_image, cv2.COLOR_BGR2GRAY) processed_image = cv2.Canny(processed_image, threshold1=200, threshold2=300) return processed_image def ss(): op = 1 with mss.mss() as sct: monitor = {"top": 40, "left": 0, "width": 800, "height": 640} while "Screen capturing": last_time = time.time() img = numpy.array(sct.grab(monitor)) gray_frame = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) res = cv2.matchTemplate(gray_frame, template, cv2.TM_CCOEFF_NORMED) loc = np.where(res >= 0.7) op += 1 print (op) for pt in zip(*loc[::-1]): cv2.rectangle(img, pt, (pt[0] + w, pt[1] + h), (0, 255, 0), 3) for p in img: pts = (pt[0],pt[1]) x = (pt[0]) y = (pt[1]) print (x) if 100 < x < 490: pyautogui.mouseDown(button='left') time.sleep(2) pyautogui.mouseUp(button='left') x = 0 break else: continue break else: continue break key = cv2.waitKey(1) if cv2.waitKey(25) & 0xFF == ord("q"): cv2.destroyAllWindows() if op > 35: return def screen_record(): sct = mss.mss() last_time = time.time() while(True): img = sct.grab(mon) print('loop took {} seconds'.format(time.time() - last_time)) last_time = time.time() img = np.array(img) processed_image = process_image(img) mean = np.mean(processed_image) print('mean = ', mean) if mean <= float(0.11): print('SSSSSSSS ') pyautogui.click(button='left') break return else: time.sleep(0.01) continue return if cv2.waitKey(25) & 0xFF == ord('q'): cv2.destroyAllWindows() break while "": time.sleep(1) pyautogui.moveTo(431,175,duration=1) pyautogui.mouseDown(button='left') pyautogui.moveTo(450.200,duration=1) pyautogui.mouseUp(button='left') time.sleep(2) screen_record() time.sleep(0.01) ss()
Quem gosta de dizer que é uma perda de tempo, vou notar que isso é apenas uma ferramenta, você pode usar essas bibliotecas em outros projetos. A própria visão computacional é usada tanto no lançamento de mísseis balísticos quanto em programas para ajudar pessoas com deficiência. Onde você decide aplicá-los, apenas seu desejo.
Obrigado a todos pela atenção.