記一次陰陽師掛機腳本開發

  最近和跟着同事一塊兒玩陰陽師,發現這個遊戲有太多重複操做了,這徹底就是浪費生命啊;因此想到用python寫一個自動掛機腳本。python

最開始想得很簡單,就是一直去找相應得按鈕,而後點擊就能夠了。因此直接用pyautogui的圖片定位和點擊功能就好了,也確實實現了,代碼以下:多線程

  

import pyautogui,time pyautogui.FAILSAFE = True '''PyAutoGUI提供了一個保護措施。當pyautogui.FAILSAFE = True時,若是把鼠標光標在屏幕左上角, PyAutoGUI函數就會產生pyautogui.FailSafeException異常,用於在程序失控時退出''' time.sleep(2) def get_point(picture): '''精確匹配某個按鈕的位置;經過傳入圖片獲取圖片在屏幕上的定位,一旦獲取到值則退出,不然繼續嘗試''' picture = './img/' + picture count = 5
    while count > 0: point = pyautogui.locateCenterOnScreen(picture) if point is not None: return point else: count -= 1

def get_range(picture): '''用模糊匹配獲得某個按鈕的大概位置,通常是在那種點擊屏幕任意位置的狀況,或只須要知道某個按鈕在不在當前屏幕的狀況使用 要動的圖片採用模糊匹配,不然精確匹配的話,圖片一直在動像素也在變化,就不能定位到了''' picture = './img/' + picture count = 5
    while count > 0: range = pyautogui.locateCenterOnScreen(picture, grayscale=True, confidence=0.5) if range is not None: return range else: count -= 1
def click_button(picture,accurate=True): '''點擊按鈕的函數,默認精確度爲True,即默認爲精確點擊,若是accurate=False,則爲模糊點擊,用於動態圖形按鈕'''
    if accurate==True: action = get_point(picture) else: action = get_range(picture) if action is not None: pyautogui.click(action,duration=0.5) def cycle_fight(): '''用戶循環重複的戰鬥場景,若是刷覺醒材料,刷御魂'''
    while True: click_button('tiaozhan.PNG') click_button('zhunbei.PNG') click_button('over.PNG') cycle_fight()

 



最後發現這樣彷佛不科學,不只慢還浪費資源;而後又想到在準備完成和戰鬥結束這段時間,有很長的空白期,徹底可讓程序中止啊,因此又出現了下面的代碼:

import pyautogui,time

pyautogui.FAILSAFE = True
'''PyAutoGUI提供了一個保護措施。當pyautogui.FAILSAFE = True時,若是把鼠標光標在屏幕左上角,
PyAutoGUI函數就會產生pyautogui.FailSafeException異常,用於在程序失控時退出'''
time.sleep(2)
def get_point(picture):
    '''精確匹配某個按鈕的位置;經過傳入圖片獲取圖片在屏幕上的定位,一旦獲取到值則退出,不然繼續嘗試'''
    picture = './img/' + picture
    count = 5
    while count > 0:
        point = pyautogui.locateCenterOnScreen(picture)
        if point is not None:
            return point
        else:
            count -= 1

def get_range(picture):
    '''用模糊匹配獲得某個按鈕的大概位置,通常是在那種點擊屏幕任意位置的狀況,或只須要知道某個按鈕在不在當前屏幕的狀況使用
     要動的圖片採用模糊匹配,不然精確匹配的話,圖片一直在動像素也在變化,就不能定位到了'''
    picture = './img/' + picture
    count = 5
    while count > 0:
        range = pyautogui.locateCenterOnScreen(picture, grayscale=True, confidence=0.5)
        if range is not None:
            return range
        else:
            count -= 1
def click_button(picture,accurate=True):
    '''點擊按鈕的函數,默認精確度爲True,即默認爲精確點擊,若是accurate=False,則爲模糊點擊,用於動態圖形按鈕'''
    if accurate==True:
        action = get_point(picture)
    else:
        action = get_range(picture)
    if action is not None:
        pyautogui.click(action,duration=0.5)
        return True   #點擊成功則返回True
    else:
        return None    #經過這個返回值斷定有沒有點擊成功

def on_fight(sec):
    '''這個函數用於模擬從【準備】到【戰鬥結束】這段時間,在這段時間裏程序應該是阻塞的,這樣就不用一直去找對應的按鈕,從而消耗大量的系統資源'''
    fight_run = click_button('zhunbei.PNG')  #點擊準備按鈕則戰鬥開始
    if fight_run is not  None:      #若是成功點擊了準備按鈕則表明戰鬥開始,程序進入尋找【戰鬥結束按鈕】的狀態
        count = 0
        while True:
            time.sleep(sec)   #設定每幾秒檢測一次戰鬥是否結束,這個值能夠具體狀況設置
            fight_over = click_button('over.PNG')
            if fight_over is not None:
                return True
            else:
                count +=1       #記錄循環次數
                if count*sec > 600:
                    '''用循環次數乘以中斷時間,大約等於戰鬥過程的時間,這裏的意思是戰鬥過程大於10分鐘,通常這種狀況,確定
                    是在點擊了準備以後,戰鬥過程當中異常中斷,這時候程序會一直陷入這個尋找戰鬥結束的死循環中,但這是沒有意義的,
                    因此直接退出整個程序'''
                    exit(1)
    else:
        return None    #若是沒有點擊【準備】按鈕,則返回爲空,繼續進入下一次尋找進入戰鬥起始按鈕的過程

def cycle_fight(sec):
    '''用戶循環重複的戰鬥場景,若是刷覺醒材料,刷御魂'''
    while True:
        click_button('tiaozhan.PNG')
        on_fight(sec)

def story_task():
    '''用於過廢話連篇的劇情'''
    while True:
        click_button('tiaoguo.PNG')
        click_button('dialogue.PNG')
        click_button('storyJump.PNG')


def explore_task(sec):
    '''用於過探索副本'''
    while True:
        click_button('fight.PNG',accurate=False)
        click_button('masterFight.PNG',accurate=False)
        on_fight(sec)

#explore_task()
# cycle_fight(10)
story_task()
這樣一來雖然下降了系統資源消耗但代碼邏輯變得極爲複雜,而後便想到用多線程封裝,以後效率確實極大的提高了:
import pyautogui,time
import threading
pyautogui.FAILSAFE = True
'''PyAutoGUI提供了一個保護措施。當pyautogui.FAILSAFE = True時,若是把鼠標光標在屏幕左上角,
PyAutoGUI函數就會產生pyautogui.FailSafeException異常,用於在程序失控時退出'''
time.sleep(2)
class FindButton(threading.Thread):
    def __init__(self, picture):
        super(FindButton, self).__init__()
        self.picture = './img/' + picture
    def run(self):
        while True:
            self.point = pyautogui.locateCenterOnScreen(self.picture, confidence=0.8)
            if self.point is not None:
                pyautogui.click(self.point, duration=0.5)
challenge = FindButton('tiaozhan.PNG')
prepare = FindButton('zhunbei.PNG')
over = FindButton('over.PNG')
challenge.start()
prepare.start()
over.start()
可是這樣一來,系統資源的消耗也成倍的增長了,至關於每多一個點擊操做,就要多使用一倍的系統資源。那不如用協程來解決吧,既是單線程,又能夠異步進行;

最後證實協程比多線程稍慢(畢竟協程是須要排隊的,協程直接的切換也是須要消耗時間的),比單線程則是快了太多了

 並且消耗的系統資源也極大的下降了(甚至比單線程的狀況還低),而且代碼也簡單了太多了!異步

import gevent import pyautogui def click(picture): picture = './img/' + picture while True: point = pyautogui.locateCenterOnScreen(picture, confidence=0.8) if point is None: gevent.sleep(1) else: pyautogui.click(point, duration=0.5) def cycle_fight(): '''用於循環重複的戰鬥場景,若是刷覺醒材料,刷御魂''' gevent.joinall([ #利用joinall方法將每一步操做加入協程池中
        gevent.spawn(click,'tiaozhan.PNG'),   #每個協程的加入方法是:(函數名,參數)
        gevent.spawn(click,'zhunbei.PNG'), gevent.spawn(click,'over.PNG') ]) def story_task(): ''''用於過廢話連篇的劇情任務''' gevent.joinall([ gevent.spawn(click, 'dialogue.PNG'), gevent.spawn(click, 'tiaoguo.PNG'), gevent.spawn(click, 'storyJump.PNG'), gevent.spawn(click, 'fight.PNG'), gevent.spawn(click, 'zhunbei.PNG'), gevent.spawn(click, 'over.PNG') ]) def explore_task(): '''用於過探索副本''' gevent.joinall([ gevent.spawn(click, 'fight.PNG'), gevent.spawn(click, 'masterFight.PNG'), gevent.spawn(click, 'zhunbei.PNG'), gevent.spawn(click, 'over.PNG') ]) cycle_fight()
相關文章
相關標籤/搜索