当前位置:主页 > 查看内容

Python脚本控制鼠标键盘

发布时间:2021-05-24 00:00| 位朋友查看

简介:import timeimport pyautogui as pgfrom PIL import Imageimport randomimport datetimeimport threadingimport osimport keyboard as kbAutoPalyFlag True# 设置 图标 boxbox_settings (1890, 870, 1920, 900)# 发起投降 按钮 boxbox_surrender (700, 820,……
import time
import pyautogui as pg
from PIL import Image
import random
import datetime
import threading
import os
import keyboard as kb

AutoPalyFlag = True

# 设置 图标 box
box_settings = (1890, 870, 1920, 900)
# 发起投降 按钮 box
box_surrender = (700, 820, 840, 860)
# 确认投降 按钮 box
box_confirm = (720, 460, 940, 520)
# 空白区域
box_empty_area = (700, 0, 800, 10)
# 再玩一次
box_play_again = (530, 830, 780, 880)

# 商店5个怪的box
champ_box = [
    (480, 930, 670, 1070),
    (680, 930, 870, 1070),
    (880, 930, 1070, 1070),
    (1080, 930, 1270, 1070),
    (1290, 930, 1480, 1070),
]
pg.FAILSAFE = False
log_path = 'log\\%s.log'%time.strftime('%Y_%m_%d_%H_%M_%S')
log_file = open(log_path, 'w', encoding='utf8')

def slow_click(p, button='PRIMARY', move_time = 0.2, down_time = 0.2, up_time = 0.2):
    pg.moveTo(p[0], p[1], duration=move_time)
    pg.mouseDown(p[0], p[1], button=button, duration = down_time)
    pg.mouseUp(p[0], p[1], button=button, duration = up_time)
    
    return True

def slow_key_press(key, down_time = 0.2):
    kb.press(key)
    time.sleep(down_time)
    kb.release(key)
    
    return True

def record_and_print_log(log):
    global log_file
    print(log)
    log_file.write(log)
    log_file.write('\n')
    return True

def get_time_fmt_str(t = None):
    if not t:
        t = time.localtime()
    return time.strftime("%Y/%m/%d %H:%M:%S", t)

def stray():
    # 在棋盘小范围内随机游荡,防止鼠标指针挡住关卡图片导致检测不到3-2关卡
    x = random.randint(500, 1200)
    y = random.randint(250, 650)

    slow_click((x,y), button='right', move_time=0.5)

    return True

# 买一个怪
def buy_single_champ(index):
    global champ_box

    if index > 4:
        index = 4
    if index < 0:
        index = 0
    
    box = champ_box[index]
    center = get_box_center(box)
    slow_click(center, move_time=0.3)
    
    return True

# 刷新商店
def refresh_shop():
    kb.press_and_release('d')
    return True

def show_emoji():
    kb.press_and_release('t')
    return True

# 提升等级
def upgrade_champ():
    kb.press_and_release('f')
    return True

def get_lol_hwnd():
    title = 'League of Legends'
    w = pg.getWindowsWithTitle(title)

    hwnd = False
    for i in w:
        if i.title == title:
            hwnd = i
            break

    return hwnd

def get_box_center(box):
    x = int((box[2] - box[0]) / 2) + box[0]
    y = int((box[3] - box[1]) / 2) + box[1]

    return (x, y)

def move_to_empty_area(lol_hwnd):
    global  box_empty_area

    # 客户端已经最小化,不移动鼠标
    if lol_hwnd.size < (1024, 768):
        return

    center = convert_lol_to_destop_point(get_box_center(box_empty_area), lol_hwnd)
    pg.moveTo(center[0], center[1], duration = 0.1)

    return True

# 将LOL客户端相对坐标根据LOL客户端位置转换为实际桌面的绝对坐标
def convert_lol_to_destop_point(p, lol_hwnd):
    x = lol_hwnd.topleft[0] + p[0]
    y = lol_hwnd.topleft[1] + p[1]

    return (x, y)

def surrender():
    global box_settings, box_surrender, box_confirm
    # center = get_box_center(box_settings)
    # 点击设置
    # slow_click(center, move_time=0.5)

    slow_key_press('esc')

    center = get_box_center(box_surrender)
    # 发起投降
    slow_click(center, move_time=0.5)

    center = get_box_center(box_confirm)
    # 确定离开
    slow_click(center, move_time=0.5)

    return True

# 卖掉候选台前三个怪,和棋盘上自动上的怪
def sell_monsters():
    slot1 = (443, 758)
    slot2 = (576, 758)
    slot3 = (696, 758)
    slot4 = (975, 672)

    pg.moveTo(slot1)
    slow_key_press('e')
    time.sleep(1)
    pg.moveTo(slot2)
    slow_key_press('e')
    time.sleep(1)
    pg.moveTo(slot3)
    slow_key_press('e')
    time.sleep(1)
    pg.moveTo(slot4)
    slow_key_press('e')

game_inactive_count = 0
# 切换到游戏
def make_game_active(game_hwnd):
    global game_inactive_count

    while not game_hwnd.isActive:
        game_hwnd.activate()
        pg.press('enter')
        time.sleep(2)
    game_inactive_count = 0


# 让游戏处于活动状态
def check_game_active(game_hwnd):
    global game_inactive_count
    if not game_hwnd.isActive:
        game_inactive_count += 1
    else :
        game_inactive_count = 0
    # 等待3 * 5秒,游戏还未切换回来,就主动切换回来
    if game_inactive_count > 3:
        make_game_active(game_hwnd)


# 开始匹配
def click_find_match(lol_hwnd):
    pic_find_match = Image.open(r'scs\find_match.jpg')
    p = pg.locateCenterOnScreen(pic_find_match, confidence=0.9)

    if p:
        slow_click(p)
        move_to_empty_area(lol_hwnd)
    else:
        return False
    
    if not pg.locateCenterOnScreen(pic_find_match, confidence=0.9):
        return True
    
    return False

# 等待太久,重新匹配
def stop_and_start_a_new_match(lol_hwnd):
    pic = Image.open(r'scs\stop.png')
    p = pg.locateCenterOnScreen(pic, confidence=0.9)
    if p:
        slow_click(p)
        move_to_empty_area(lol_hwnd)
    else:
        record_and_print_log('找不到停止按钮!')
        return False
    
    time.sleep(1)
    return  click_find_match(lol_hwnd)

# 等待并接受对局
def accept_match(lol_hwnd):
    # 5分钟未进入游戏,直接重新匹配
    timeout = 5 * 60
    start_time = time.time()
    
    pic_accept = Image.open(r'scs\accept.jpg')
    while time.time() - start_time < timeout * 10:
        while time.time() - start_time < timeout:
            p = pg.locateCenterOnScreen(pic_accept, confidence = 0.93)
            if p:
                slow_click(p)
                move_to_empty_area(lol_hwnd)
            # 客户端已最小化,正在启动游戏
            if lol_hwnd.size < (1024, 768):
                return True
            time.sleep(1)
        # 等待太久,重新匹配
        if not stop_and_start_a_new_match(lol_hwnd):
            return False

    record_and_print_log("10次超时未找到对局!")
    return False

# 寻找对局 -> 队列中 -> 接受 -> 开始加载
# 寻找对局 -> 队列中 -> 接受 -> 有人拒绝 -> 队列中
def pg_find_match(lol_hwnd):
    click_find_match(lol_hwnd)
    return accept_match(lol_hwnd)

def pg_wait_loading(lol_hwnd):
    pic = Image.open(r'scs\1_1.jpg')

    while True:
        # pyautogui 模块检测关卡
        box = pg.locateOnScreen(pic, confidence=0.9)
        if box:
            return True
        time.sleep(2)
    return True

WaitStageFlag = True

def change_wait_flag_callback():
    global WaitStageFlag
    record_and_print_log("17分钟未检测到3-2回合,直接进行下一步操作")
    WaitStageFlag = False
    return True

# 空城速八
def pg_quick_wait_quit():
    global game_inactive_count

    print("Start wait quit button")
    pic = Image.open(r'scs\quit.png')

    client_title = 'League of Legends (TM) Client'
    game_hwnd = pg.getWindowsWithTitle(client_title)[0]
    
    while True:
        # 让游戏处于活动状态
        check_game_active(game_hwnd)
        # 游戏被切换出去了,此时不操作鼠标键盘
        if game_inactive_count > 0:
            time.sleep(5)
            continue

        box = pg.locateOnScreen(pic, confidence=0.95)
        if box:
            slow_click(pg.center(box))
            break
        case = random.randint(1,100)
        # %50 概率游荡
        if case <= 50:
            stray()
        case = random.randint(1,100)
        # %50 概率发表情
        if case <= 50:
            show_emoji()
        
        # case = random.randint(1,100)
        # # %5 概率升级
        # if case >= 85 and case < 90:
        #     upgrade_champ()
        
        sell_monsters()

    return True

# 乱拿等死
def pg_slow_wait_quit():
    global game_inactive_count

    print("Start wait quit button")
    pic = Image.open(r'scs\quit.png')

    client_title = 'League of Legends (TM) Client'
    game_hwnd = pg.getWindowsWithTitle(client_title)[0]
    
    while True:
        # 让游戏处于活动状态
        check_game_active(game_hwnd)
        # 游戏被切换出去了,此时不操作鼠标键盘
        if game_inactive_count > 0:
            time.sleep(5)
            continue

        box = pg.locateOnScreen(pic, confidence=0.95)
        if box:
            slow_click(pg.center(box))
            break

        if game_inactive_count > 0:
            time.sleep(5)
            continue

        case = random.randint(1,100)
        # %40 概率游荡
        if case <= 40:
            stray()
        
        if game_inactive_count > 0:
            time.sleep(5)
            continue
        case = random.randint(1,100)
        # %25 概率买1个英雄
        if case >= 25 and case < 50:
            buy_single_champ(random.randint(0, 4))
        
        # case = random.randint(1,100)
        # %0 概率刷新商店
        # if case == 0:
            # refresh_shop()
        
        if game_inactive_count > 0:
            time.sleep(5)
            continue
        case = random.randint(1,100)
        # %30 概率发表情
        if case <= 30:
            show_emoji()
        
        if game_inactive_count > 0:
            time.sleep(5)
            continue
        
        case = random.randint(1,100)
        # %5 概率升级
        if case >= 85 and case < 90:
            upgrade_champ()
        
        time.sleep(1)

    return True

# 速度投降
def pg_wait_stage_3_2():
    global WaitStageFlag, game_inactive_count
    pic = Image.open(r'scs\3_2.jpg')

    WaitStageFlag = True

    # 启动一个Timer,17分钟未检测到3-2回合,直接进行下一步
    t = threading.Timer(17 * 60, change_wait_flag_callback)
    t.start()

    client_title = 'League of Legends (TM) Client'
    game_hwnd = pg.getWindowsWithTitle(client_title)[0]

    while WaitStageFlag:
        # 让游戏处于活动状态
        check_game_active(game_hwnd)
        # 游戏被切换出去了,此时不操作鼠标键盘
        if game_inactive_count > 0:
            time.sleep(5)
            continue
        # pyautogui 模块检测关卡
        box = pg.locateOnScreen(pic, confidence=0.9)
        if box:
            # 检测到3-2,停止Timer
            t.cancel()
            return True

        if game_inactive_count > 0:
            time.sleep(5)
            continue

        case = random.randint(1,100)
        # %40 概率游荡
        if case <= 40:
            stray()
        
        if game_inactive_count > 0:
            time.sleep(5)
            continue
        case = random.randint(1,100)
        # %25 概率买1个英雄
        if case >= 25 and case < 50:
            buy_single_champ(random.randint(0, 4))
        
        # case = random.randint(1,100)
        # %0 概率刷新商店
        # if case == 0:
            # refresh_shop()
        
        if game_inactive_count > 0:
            time.sleep(5)
            continue
        case = random.randint(1,100)
        # %30 概率发表情
        if case <= 30:
            show_emoji()
        
        if game_inactive_count > 0:
            time.sleep(5)
            continue
        
        case = random.randint(1,100)
        # %5 概率升级
        if case >= 85 and case < 90:
            upgrade_champ()
        
        time.sleep(1)
    
    return True

def close_award_interface(lol_hwnd):
    ok_box = (lol_hwnd.centerx - 100, lol_hwnd.bottom - 60, 200, 40)
    c = pg.center(ok_box)
    slow_click(c)
    move_to_empty_area(lol_hwnd)

    return True

def pg_wait_surrender_finish(lol_hwnd):
    client_title = 'League of Legends (TM) Client'
    times = 0
    while True:
        time.sleep(1)
        times += 1
        if pg.getWindowsWithTitle(client_title) == []:
            break
        
        if times % 10 == 0:
            print("pg_wait_surrender_finish %d sec, still wait client over!"%times)
    
    # 检测结算界面是否打开
    while True:
        pic = Image.open(r'scs\end.jpg')
        box = pg.locateOnScreen(pic, confidence = 0.9)
        if box:
            break
        
        record_and_print_log("Not Found end.jpg!")
        # 结算界面已打开,但被奖励界面遮挡
        if lol_hwnd.size == (1600, 900):
            record_and_print_log("try to close_award_interface!")
            close_award_interface(lol_hwnd)

        time.sleep(3)

    return True

def pg_play_again(lol_hwnd):
    global box_play_again, box_empty_area
    center = convert_lol_to_destop_point(get_box_center(box_play_again), lol_hwnd)
    pg.click(center[0], center[1], duration = 0.3)  # 点击再玩一次
    move_to_empty_area(lol_hwnd)

    time.sleep(1)
    pic = Image.open(r'scs\end.jpg')

    pic_find_match = Image.open(r'scs\find_match.jpg')
    box = pg.locateOnScreen(pic_find_match, confidence=0.9)
    while not box:
        if pg.locateOnScreen(pic, confidence = 0.9) != []:
            pg.click(center[0], center[1], duration = 0.3)  # 点击再玩一次
            move_to_empty_area(lol_hwnd)
        else:
            # 奖励界面遮挡
            close_award_interface(lol_hwnd)

        time.sleep(1)
        box = pg.locateOnScreen(pic_find_match, confidence=0.9)

    return True

def pg_stop_play():
    global AutoPalyFlag
    AutoPalyFlag = False
    return True

# 手动结束脚本命令,按Ctrl+Alt+q即可设置停止运行标志
kb.add_hotkey('ctrl+alt+q', pg_stop_play)

def pg_main():
    global AutoPalyFlag, log_file

    w = get_lol_hwnd()
    if not w:
        print("游戏未启动,请启动游戏后再运行脚本!")
        return False

    play_times = 0
    start_time = time.localtime()
    game_time_list = []

    # record_and_print_log("[%s] pg_find_match"%get_time_fmt_str())
    # pg_find_match(w)
    # record_and_print_log("[%s] pg_wait_loading"%get_time_fmt_str())
    # pg_wait_loading(w)
    # record_and_print_log("[%s] pg_quick_wait_quit"%get_time_fmt_str())
    # pg_quick_wait_quit()
    # record_and_print_log("[%s] pg_wait_surrender_finish"%get_time_fmt_str())
    # pg_wait_surrender_finish(w)
    # play_times += 1
    # record_and_print_log("[%s] pg_play_again"%get_time_fmt_str())
    # pg_play_again(w)

    while AutoPalyFlag:
        # 游戏开始时间
        game_start = time.time()
        record_and_print_log("[%s] pg_find_match"%get_time_fmt_str())
        pg_find_match(w)
        record_and_print_log("[%s] pg_wait_loading"%get_time_fmt_str())
        pg_wait_loading(w)

        case = random.randint(1, 3)
        # case = 1
        if case == 1:
            record_and_print_log("[%s] pg_wait_stage_3_2"%get_time_fmt_str())
            pg_wait_stage_3_2()
            record_and_print_log("[%s] surrender"%get_time_fmt_str())
            surrender()
            record_and_print_log("[%s] pg_wait_surrender_finish"%get_time_fmt_str())
        elif case == 2:
            record_and_print_log("[%s] pg_quick_wait_quit"%get_time_fmt_str())
            pg_quick_wait_quit()
        elif case == 3:
            record_and_print_log("[%s] pg_slow_wait_quit"%get_time_fmt_str())
            pg_slow_wait_quit()
        pg_wait_surrender_finish(w)
        play_times += 1
        record_and_print_log("[%s] pg_play_again"%get_time_fmt_str())

        # 游戏结束时间
        game_end = time.time()
        game_time = int(game_end - game_start)
        game_time_list.append(game_time)

        if not AutoPalyFlag:
            break
        pg_play_again(w)
        
    # 统计每局时间,写入到文件
    for i in range(len(game_time_list)):
        seconds = game_time_list[i] % 60
        minutes = int(game_time_list[i] / 60)
        info = "第%d局用时[%d]分[%d]秒"%(i + 1, minutes, seconds)
        record_and_print_log(info)

    # 输出统计信息
    end_time = time.localtime()

    record_and_print_log("[%s] 开始挂机"%get_time_fmt_str(start_time))
    record_and_print_log("[%s] 结束挂机"%get_time_fmt_str(end_time))

    diff_time_sec = time.mktime(end_time) - time.mktime(start_time)
    t_s = int(diff_time_sec) % 60
    diff_time_sec /= 60
    # 总共所用分钟数
    total_minutes = diff_time_sec
    t_m = int(diff_time_sec) % 60
    diff_time_sec /= 60
    t_h = int(diff_time_sec)

    average_minutes = total_minutes / play_times
    t_ave_m = int(average_minutes)
    t_ave_s = int((average_minutes - t_ave_m) * 60)
    record_and_print_log("共挂机[%d]小时[%d]分钟[%d]秒,挂机[%d]局,平均[%d]分钟[%d]秒一局"%(t_h, t_m, t_s, play_times, t_ave_m, t_ave_s))

    log_file.close()

    return True

if __name__ == '__main__':
    pg_main()
    os.system("pause")

测试程序:win10下打包好的最新程序和截图资源文件:某度网盘? 提取码:lek7

;原文链接:https://blog.csdn.net/qiximenghu/article/details/115534452
本站部分内容转载于网络,版权归原作者所有,转载之目的在于传播更多优秀技术内容,如有侵权请联系QQ/微信:153890879删除,谢谢!

推荐图文


随机推荐