在Python中检测多个像素并并行单击它们的更快方法?

2024-05-19 17:08:16 发布

您现在位置:Python中文网/ 问答频道 /正文

我想编写一个机器人,可以玩一个叫做“钢琴瓷砖”的游戏。基本上有四条垂直车道,每条车道上都有黑色瓷砖掉落。玩家需要在它们到达屏幕末端之前单击它们。玩的时候速度越来越快

我的目标是获得尽可能高的分数。世界纪录目前为每秒17次点击(瓦片/秒)。我不能得到任何高于15点击/秒,但我只是不能告诉我在哪里我的脚本慢下来

我的第一种方法是用pyautogui.pixel(x,y)检查一个像素/通道,如果它的rgb值==瓷砖的颜色-单击该位置。使用该变体得分~10次点击/秒

在那之后,我计算了一个偏移量来保持加速度,基本上我在点击的y位置上增加了一个数字,这使我的点击率达到了大约12次/秒

我把它录下来,一帧一帧地看着它失败。发生的事情是,最终游戏变得如此之快,以至于示例脚本无法在“通道1”中检测到像素,而单击发生在“通道4”中

我提出的解决方案是多处理和pypy

    import pyautogui
    import multiprocessing
    import time


    time.sleep(2)
    print("READYprint")



    def Lane1():
        a = 0
        b = 0
        pyautogui.PAUSE = 0
        while True:

            if pyautogui.pixel(800, 520) [0] == 0:
                pyautogui.click(x=800, y=520 + b)
                
                a = a + 1
                b = a // 15
            
            
                

    def Lane2():
        a = 0
        b = 0
        pyautogui.PAUSE = 0
        while True:

            if pyautogui.pixel(902, 520) [0] == 0:
                pyautogui.click(x=902, y=520 + b)
                
                a = a + 1
                b = a // 15
            
                

    def Lane3():
        a = 0
        b = 0
        pyautogui.PAUSE = 0
        while True:

            if pyautogui.pixel(1033, 520) [0] == 0:
                pyautogui.click(x=1033, y=520 + b)
                
                a = a + 1
                b = a // 15
            
                

    def Lane4():
        a = 0
        b = 0
        pyautogui.PAUSE = 0
        while True:

            if pyautogui.pixel(1134, 520) [0] == 0:
                pyautogui.click(x=1134, y=520 + b)
                
                a = a + 1
                b = a // 15
            
                

    p1 = multiprocessing.Process(target=Lane1)
    p2 = multiprocessing.Process(target=Lane2)
    p3 = multiprocessing.Process(target=Lane3)
    p4 = multiprocessing.Process(target=Lane4)


    if __name__ == "__main__":
        p1.start()
        p2.start()
        p3.start()
        p4.start()


我还运行了一个测试,以测试脚本的性能

import time
import pyautogui

start_time = time.time()


def test():
    a = 0
    b = 0
    pyautogui.PAUSE = 0
    while a < 100:
     
        if pyautogui.pixel(970, 208) [0] == 255:
        
            pyautogui.click(x=970, y=208 + b)
            a = a + 1
            b = a // 15


test()

    
print("--- %s seconds ---" % (time.time() - start_time))

输出:--1.7149109840393066秒---,表示100次“获取rgb值+单击,如果为白色。”

我不知道为什么机器人那么“慢”。当它失败的时候离0017很远。。。秒/选中\u单击。原因可能是多重处理吗?虽然它确实快了一点,但应该快很多。我也在没有pypy的情况下运行了它。如果没有pypy JIT,则每秒可点击约13次


Tags: importtruetargetiftimedefmultiprocessingprocess
2条回答

这不是对你问题的直接回答,但同时获得所有四条车道的屏幕截图可能会更快pyautogui.pixel()combines屏幕截图和getpixel函数。因此,您的代码将为每条车道分别获取一个屏幕截图。更快的方法可能是:

xlocations= [800,902,1033,1134]
yloc=520
while True:
    im = pyautogui.screenshot()
    for xloc in xlocations: 
       if im.getpixel((xloc, yloc)) [0] == 0:
          pyautogui.click(x=xloc, y=yloc+ b)
          a = a + 1
          b = a // 15
    

我提出的“最终”解决方案如下:

import time
import win32api, win32con, win32ui
import multiprocessing

time.sleep(1)
print("RDY")

def Lane1():

    
    window_name = "App Player" 
    wd = win32ui.FindWindow(None, window_name)
    

    while True:
        dc = wd.GetWindowDC()
        try:

             
            j = dc.GetPixel (35,230)  
            
            if j == 0:
                
                win32api.SetCursorPos((35, 230))
                win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN,0,0)
                time.sleep(0.01)
                win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP,0,0)
            dc.DeleteDC()

        except win32ui.error:
            print("we got an error 1")
            continue

def Lane2():

    
    window_name = "App Player" 
    wd = win32ui.FindWindow(None, window_name)
     

    while True:
        dc = wd.GetWindowDC()

        try:

            
            j = dc.GetPixel (60,240)  
            
            if j == 0:
                
                win32api.SetCursorPos((60, 240))
                win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN,0,0)
                time.sleep(0.01)
                win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP,0,0)
            dc.DeleteDC()

        except win32ui.error:
            print("we got an error 2")
            continue

def Lane3():

    
    window_name = "App Player" 
    wd = win32ui.FindWindow(None, window_name)
    
    while True:
        dc = wd.GetWindowDC()

        try:

            
            j = dc.GetPixel (120,250)  
            
            if j == 0:
                
                win32api.SetCursorPos((120, 250))
                win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN,0,0)
                time.sleep(0.01)
                win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP,0,0)
            dc.DeleteDC()

        except win32ui.error:
            print("we got an error 3")
            continue

def Lane4():

    
    window_name = "App Player" 
    wd = win32ui.FindWindow(None, window_name)
    

    while True:
        dc = wd.GetWindowDC()
         

        try:

            
            j = dc.GetPixel (180,260)  
            
            if j == 0:
                
                win32api.SetCursorPos((180, 260))
                win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN,0,0)
                time.sleep(0.01)
                win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP,0,0)
            dc.DeleteDC()

        except win32ui.error:
            print("we got an error 4")
            continue
        

        




p1 = multiprocessing.Process(target=Lane1)
p2 = multiprocessing.Process(target=Lane2)
p3 = multiprocessing.Process(target=Lane3)
p4 = multiprocessing.Process(target=Lane4)


if __name__ == "__main__":
    p1.start()
    p2.start()
    p3.start()
    p4.start()

    p1.join()
    p2.join()
    p3.join()
    p4.join()

我检查了不同y位置上的像素,以确保不同进程之间没有这种竞争条件,这确实会导致错误。同时,它也有助于保持游戏窗口尽可能小,因为模拟器往往是滞后的

在这个版本的机器人中,点击次数大约为22次/秒

相关问题 更多 >