金铲铲S13双城之战自动拿牌助手2.0

金铲铲S13双城之战自动拿牌助手2.0

书接上文:
金铲铲S13双城之战自动拿牌助手1.0

更新了UI界面做配置和控制;
新增异常突变参数;
压缩包里的内容
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
打开程序有2个窗口
1个黑窗口显示日志信息
1个Coordinate App窗口用来配置和控制
打开程序有2个窗口
点击按钮:“获取坐标” 即可开始自动拿牌
点击停止按钮可以停止拿牌
打开程序以前要先打开【雷电模拟器】
并且雷电模拟器的Title要为:雷电模拟器在这里插入图片描述
比较适配1080p的显示器
雷电模拟器设置
https://help.ldmnq.com/docs/7oTh0M
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
雷电模拟器快捷键设置
雷电模拟器快捷键设置

代码在GitHub链接

import threading
import tkinter as tk
from tkinter import ttk
import pyautogui
import time
import datetime
from paddleocr import PaddleOCR
import logging


max_screen_width, max_screen_height = pyautogui.size()
welcome = f'注意:请遵守一下规则:\n您当前屏幕像素宽度:{max_screen_width} 屏幕高度:{max_screen_height}\n' \
          f'因此,在填入x,y参数的时候\nx的值要在1到当前屏幕像素宽度 {max_screen_width} 之间\n' \
          f'y的值要在1到屏幕高度:{max_screen_height}之间'
pyautogui.alert(welcome)
# 定义全局变量大拇指的;异常突变的
x_coords = [720, 914, 1104, 1299, 1492]
y_coord = 968
param_yctb_name = ""

# 记录打印日志时间,设置打印等待日志间隔
global_now = datetime.datetime.now()
global_init_sec = global_now.second

thumbs_x_y = (
    (x_coords[0], y_coord),
    (x_coords[1], y_coord),
    (x_coords[2], y_coord),
    (x_coords[3], y_coord),
    (x_coords[4], y_coord)
)


class CoordinateApp:
    def __init__(self, root):
        self.root = root
        self.find_Ld_module()
        self.root.title("Coordinate App")
        self.thread = None
        # 创建全局停止事件
        global stop_event
        stop_event = threading.Event()
        # 创建标签和输入框
        print("CoordinateApp run")
        self.start_bt = None
        self.stop_bt = None
        self.create_widgets()
        # 设置窗口大小和位置 (宽x高+X偏移+Y偏移)
        self.root.geometry("550x350+100+100")
        # 绑定关闭事件
        self.root.protocol("WM_DELETE_WINDOW", self.on_closing)

    def create_widgets(self):
        self.x_entries = []
        self.y_entry = None
        self.param_entry = None

        # 只允许输入数字的验证函数
        def only_numbers(char):
            return char.isdigit()

        validation = self.root.register(only_numbers)

        for i in range(5):
            # X 坐标标签和输入框
            x_label = ttk.Label(self.root, text=f"X 坐标 {i + 1}:")
            x_label.grid(column=0, row=i, padx=5, pady=5, sticky="W")

            x_entry = ttk.Entry(self.root, validate="key", validatecommand=(validation, '%S'))
            x_entry.grid(column=1, row=i, padx=5, pady=5, sticky="W")
            x_entry.insert(i, x_coords[i])  # 设置默认值
            self.x_entries.append(x_entry)

        # Y 坐标标签和输入框
        y_label = ttk.Label(self.root, text="Y 坐标:")
        y_label.grid(column=0, row=5, padx=5, pady=5, sticky="W")

        self.y_entry = ttk.Entry(self.root, validate="key", validatecommand=(validation, '%S'))
        self.y_entry.grid(column=1, row=5, padx=5, pady=5, sticky="W")
        self.y_entry.insert(0, y_coord)

        # 异常突变参数标签和输入框
        param_label = ttk.Label(self.root, text="异常突变:")
        param_label.grid(column=0, row=6, padx=5, pady=5, sticky="W")

        self.param_entry = ttk.Entry(self.root)
        self.param_entry.grid(column=1, row=6, padx=5, pady=5, sticky="W")

        self.param_entry = ttk.Combobox(self.root, values=["超高速", "狂战之怒", "力量训练", "防御型护盾", "即兴发挥", "双刀流", "壁垒", "终结者", "坚不可破", "荆棘满途", "恃强凌弱", "护甲山崩", "石头皮肤", "斥力发生器", "地下拳王", "魔法训练", "鹰眼", "奥术浩荡", "隐形", "友谊之力", "泰坦打击", "最后机会", "慢炖", "法师护甲", "恕瑞玛的传承", "千刀斩", "重量级打击手", "分享你的能量", "名片", "势不可挡", "真的会蟹", "史莱姆时间", "魔法专家", "翻盘故事", "防御专家", "物理专家", "冰霜触摸", "小我多多", "巨人体型", "根深蒂固", "连杀", "猎头者", "法强吸收", "攻击吸收", "火球", "贪财化身", "双狼佣兽", "剔除弱者", "深入敌阵", "迷失于未知", "龙魂", "绝不浪费", "镭射眼", "终极英雄", "震撼登场", "渴望能量", "星原之准"])
        self.param_entry.grid(column=1, row=6, padx=5, pady=5, sticky="W")
        self.param_entry.set('超高速')  # 设置默认值

        # 获取坐标按钮
        get_button = ttk.Button(self.root, text="获取坐标", command=self.get_coordinates)
        get_button.grid(column=0, row=7, padx=5, pady=5, sticky="W")
        self.start_bt = get_button

        # 显示坐标的标签
        self.coord_label = ttk.Label(self.root, text="当前坐标: ")
        self.coord_label.grid(column=0, row=8, columnspan=2, padx=5, pady=5)

        # 创建按钮2:停止线程
        stop_button = ttk.Button(self.root, text="停止", command=self.stop_thread_func)
        stop_button.grid(column=1, row=7, padx=10, pady=10)
        stop_button.config(state='disabled')  # 初始状态为禁用
        self.stop_bt = stop_button

    def get_coordinates(self):
        global x_coords, y_coord, param_yctb_name, thumbs_x_y
        x_coords = [int(entry.get()) for entry in self.x_entries]
        y_coord = int(self.y_entry.get())
        param_yctb_name = self.param_entry.get()
        self.coord_label.config(text=f"当前坐标: {[(x, y_coord) for x in x_coords]}, 异常突变参数: {param_yctb_name}")
        thumbs_x_y = (
            (x_coords[0], y_coord),
            (x_coords[1], y_coord),
            (x_coords[2], y_coord),
            (x_coords[3], y_coord),
            (x_coords[4], y_coord)
        )
        print(f"输入参数:{thumbs_x_y} 异常突变:{param_yctb_name}")
        if self.thread is None or not self.thread.is_alive():
            stop_event.clear()
            self.thread = threading.Thread(target=GetCard().get_cards_and_yctb)
            self.thread.start()
            self.start_bt.config(state='disabled')  # 禁用启动按钮
            self.stop_bt.config(state='normal')  # 启用停止按钮

    def stop_thread_func(self):
        print(f'stop_thread_func: self.thread={self.thread}')
        if self.thread is not None:
            stop_event.set()
            self.thread.join()
            self.thread = None
            self.start_bt.config(state='normal')  # 禁用启动按钮
            self.stop_bt.config(state='disabled')  # 启用停止按钮

    def on_closing(self):
        print('关闭窗口')
        self.stop_thread_func()
        self.root.destroy()

    # 找到雷电模拟器
    def find_Ld_module(self):
        try:
            # 获取雷电模拟器 将雷电模拟器窗口最大化,使窗口处于最前面
            win = pyautogui.getWindowsWithTitle('雷电模拟器')
            if len(win) > 0:
                print('找到雷电模拟器窗口了')
            win[0].maximize()
            win[0].activate()
        except BaseException as e:
            print('没找到雷电模拟器窗口')
            pyautogui.alert('没找到雷电模拟器窗口,请先打开雷电模拟器,再重新启动本程序,点击确认后程序就会关闭')
            exit(0)


class GetCard:
    def __init__(self):
        # 控制识别组件日志频率
        logging.basicConfig(level=logging.INFO)
        # 假设ppocr使用的是名为'ppocr'的logger
        logger_ppocr = logging.getLogger('ppocr')
        logger_ppocr.setLevel(logging.INFO)

    def get_cards_new(self):
        global global_init_sec, thumbs_x_y
        for index, thumb in enumerate(thumbs_x_y):
            thumb_color = pyautogui.pixel(thumb[0], thumb[1])
            # print(index, f'x={thumb[0]},y={thumb[1]}', thumb_color[0], thumb_color[1], thumb_color[2])
            # RGB三色
            red = 240 < thumb_color[0]
            green = 240 < thumb_color[1]
            blue = 200 < thumb_color[2]

            # not_white_color 白色背景会影响程序判断,对白色的处理
            if thumb_color[0] == 255 and thumb_color[1] == 255 and thumb_color[2] == 255:
                print('当前屏幕显示背景在5个大拇指的位置有白色,请使用ALT+Tab组合键切出此窗口或关闭程序')
                time.sleep(3)
                continue
            if thumb_color[0] == 245 and thumb_color[1] == 245 and thumb_color[2] == 245:
                print('当前屏幕显示背景在5个大拇指的位置有杂色,请使用ALT+Tab组合键切出此窗口或关闭程序')
                time.sleep(3)
                continue

            if red and green and blue:
                print(index + 1, "真的有true,即将点击", thumb[0], thumb[1],datetime.datetime.now())
                # pyautogui.click(thumb[0], thumb[1])
                # 改为模拟键盘按钮
                pyautogui.press(str(index + 1))
        # 获取当前时间
        now = datetime.datetime.now()
        # 格式化时间为“时:分:秒”
        formatted_time = now.strftime("%H:%M:%S")
        if abs(now.second - global_init_sec) >= 10:
            # print("当前时间(时:分:秒):", formatted_time)
            print("da等待大拇指出现...", formatted_time)
            global_init_sec = now.second

    def get_cards_and_yctb(self):
        global param_yctb_name, thumbs_x_y
        print(f'get_cards_and_yctb:{thumbs_x_y},{param_yctb_name}')
        # 4-6阶段有异常突变,记录4-6出现的位置
        left4_6 = 686
        top4_6 = 42
        width4_6 = 60
        height4_6 = 25

        # 异常突变 名称 出现的位置 一个字 宽38
        left_yctb = 574
        top_yctb = 870
        width_yctb = 118
        height_yctb = 36
        # 4-6得算作英文来识别
        ocr_en = PaddleOCR(use_angle_cls=True, lang="en")
        ocr = PaddleOCR(use_angle_cls=True, lang="ch")
        stage_flag = False
        # 记录打印日志时间,设置打印等待日志间隔
        init_sec2 = datetime.datetime.now().second
        yctb_stage = '4-6'
        yctb_stage_recycle = '4-6'
        # 和启动停止按钮线程联动
        while not stop_event.is_set():
            time.sleep(0.06)
            screen4_6 = pyautogui.screenshot(region=(left4_6, top4_6, width4_6, height4_6))
            screen4_6.save(f"stage_screenshot4_6.png")

            screen4_6 = pyautogui.screenshot(region=(left_yctb, top_yctb, width_yctb, height_yctb))
            screen4_6.save(f"yctb_screenshot.png")

            ocr_en_result_list = ocr_en.ocr('stage_screenshot4_6.png', cls=True)
            ocr_en_result = ocr_en_result_list[0]
            if ocr_en_result is not None:
                # 捕获到字符了
                stage_num = ocr_en_result[0][1][0]
                # 4-6
                if yctb_stage == stage_num:
                    print('ocr到4-6阶段')
                    stage_flag = True
                    # 记录开始时间的时间戳
                    start_time = time.time()
                    # 判断 异常突变 名称
                    while stage_flag:
                        screen4_6 = pyautogui.screenshot(region=(left_yctb, top_yctb, width_yctb, height_yctb))
                        screen4_6.save(f"yctb_screenshot.png")
                        ocr_result_list = ocr.ocr('yctb_screenshot.png', cls=True)
                        ocr_result = ocr_result_list[0]
                        if ocr_result is not None:
                            # 获取当前时间的时间戳
                            current_time = time.time()
                            # 计算时间差
                            time_difference = current_time - start_time
                            # 判断时间差是否达到或超过60秒 # 退出循环
                            if time_difference >= 60:
                                print('4-6选择异常突变超时')
                                stage_flag = False
                                yctb_stage = ''
                            # 异常突变名6称str
                            print('异常突变名称:', ocr_result[0][1][0])
                            # 最长5个字的,最短2个字的; 2个字的会俩字(
                            # 先对上2个字 3个字的又2个魔法训练,魔法专家
                            if len(str(ocr_result[0][1][0])) == 3:
                                if param_yctb_name[:3] == ocr_result[0][1][0]:
                                    print('====名称对上了,准备按钮6===')
                                    pyautogui.press('6')
                                    stage_flag = False
                                    yctb_stage = ''
                                    print('****按了6,异常突变暂时结束!****')
                            if len(str(ocr_result[0][1][0])) > 3:
                                if param_yctb_name[:2] == str(ocr_result[0][1][0])[:2]:
                                    print('====名称对上了,准备按钮6===')
                                    pyautogui.press('6')
                                    stage_flag = False
                                    yctb_stage = ''
                                    print('****按了6,异常突变暂时结束!****')
                else:
                    # 不是4-6,但是是2和3阶段
                    if stage_num is not None and str(stage_num).startswith('2-'):
                        print('ocr二阶段,时间:', datetime.datetime.now().strftime("%H:%M:%S"))
                        yctb_stage = yctb_stage_recycle
                    if stage_num is not None and str(stage_num).startswith('3-'):
                        print('ocr三阶段,时间:', datetime.datetime.now().strftime("%H:%M:%S"))
                        yctb_stage = yctb_stage_recycle
                    # 获取当前时间
                    now = datetime.datetime.now()
                    # 格式化时间为“时:分:秒”
                    formatted_time = now.strftime("%H:%M:%S")
                    if abs(now.second - init_sec2) >= 10:
                        print('ocr截取回合数:', stage_num, "等待匹配到正确的回合数", formatted_time)
                        init_sec2 = now.second
                    # 没有捕获4-6阶段的字符,执行拿卡操作
                    self.get_cards_new()
            else:
                self.get_cards_new()


if __name__ == "__main__":
    root = tk.Tk()
    app = CoordinateApp(root)
    root.mainloop()

目前基本可用,但还不是很好用,欢迎沟通交流!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

庄毕楠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值