[Из песочницы] Пишем бот для рыбалки в игре Albion Online на языке Python

[Из песочницы] Пишем бот для рыбалки в игре Albion Online на языке Python

Всем привет, я являюсь счастливым пользователем операционной системы GNU/Linux.И как многим известно, игрушек идущих на линукс без дополнительных танцев с бубном намного меньше чем в «Винде».

И еще меньше игр в жанре MMORPG.

Однако, где-то пол года или год назад я узнал что под линукс портировали игру Albion Online.
Игра очень занимательная, однако занимает достаточно большое количество времени. И дабы не тратить свои драгоценные часы жизни по напрасну, я решил написать бота. Который будет фармить мне ресурсы, пока я буду заниматься своими делами.

В игре есть много видов ремесла, можно рубить лес, камни копать, даже выращивать огороды, однако мой выбор был сделан в пользу рыбалки.

Итак, суть рыбалки в альбион онлайн проста, берете удочку, подходите к водоему, зажимаете кнопку, дабы закинуть наживку, ждете в течении определённого времени поклевки.

image

Когда клюет, вы должны опять нажать на кнопки и сыграть в мини-игру.

Тут потребуется попеременно то тянуть, то не тянуть удочку, в зависимости от движений поплавка. Поплавок движется всегда случайно, с разными последовательностями и скоростями. И если вы все сделаете верно и поплавок не выйдет за прелы допустимой зоны, то вы выловите рыбу.

Итак, все это дело мы будем автоматизировать. По средствам компьютерного языка python. Начать я решил с самого сложного, а именно с момента, где начинается игра с поплавком. Тут снова мне на выручку пришла моя любимая библиотека с компьютерным зрением OpenCV. Запустив ее мы можем обнаруживать объекты к примеру на картинках. Однако сама библиотека не знает что именно нам нужно обнаружить. Конечно существуют множество шаблонов где представлены различные предметы для их определения. Однако, там точно нет поплавков для Albion Online.

Зато в данной библиотеке есть замечательная функция поиска по заданному шаблону. И в качестве шаблона я просто взял скриншот нашего поплавка.

image

И как мы видим все прекрасно нашлось на картинке.

А разница между картинкой и потоковым виде не велика, ведь по сути это просто поток картинок с очень быстрой скоростью, и несколько строчек кода. И вот мы уже можем находить поплавок на потоковом видео.

Код

import 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 

Идем далее. Сам поплавок двигается туда-сюда и мы также должны его двигать, нажимая кнопку на мышке.

А посему, нам нужны его координаты. И для этого нас выручают вот эти строчки.

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) 

Затем мы просто воспользуемся библиотекой PyAutoGUI, которая будет зажимать кнопку мыши и отжимать ее с определенной периодичностью.

if 100 < x < 500:                         pyautogui.mouseDown(button='left')                         time.sleep(1)                         pyautogui.mouseUp(button='left')                         x = 0 

И сама мини игра успешно выигрывается.

image

Засунем все это дело в функцию и пока оставим.

Затем вернемся к изначальной части, где мы должны следить за поплавком.

Тут все несколько иначе, допустим мы можем определить, куда закинется поплавок, и попробовать анализировать ту часть экрана на наличие поплавка. Однако поплавок закинутый в воду предстает под разными углами и постоянно колышется.

В таком случае мы возьмём тот несколько иной метод. Суть его в том, что мы анализируем, скажем так разницу в пикселях внутри отслеживаемого фрагмента. Которая, если поплавка нет приближается к нулю.

В итоге было найдено оптимальное значение при котором при исчезновении поплавка, мы можем производить действия.

Код

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() 

Вот полная видео инструкция и пример работы данного бота:

Есть правда некоторые нюансы в том что там надо шаманить с цифрами, так как эти цифры подобраны под мой монитор, локацию, персонажа и экипировку. Но я думаю для грамотного пижониста это не составит проблем.

Весь скрипт:

Код

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() 

Те кто любит сказать, что это бесполезная трата времини, я замечу, что это лишь инструмент, эти библиотеки вы можете применить и в других проектах. Само компьютерное зрение применяется как при наведении баллистических ракет, так и в программах для помощи инвалидам. Куда вы решите их применить, только ваше желание.

Всем спасибо за внимание.

 
Источник

Читайте также