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


  最近和跟着同事一起玩陰陽師,發現這個游戲有太多重復操作了,這完全就是浪費生命啊;所以想到用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()

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM