记一次阴阳师挂机脚本开发

  最近和跟着同事一块儿玩阴阳师,发现这个游戏有太多重复操做了,这彻底就是浪费生命啊;因此想到用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()
相关文章
相关标签/搜索