首页 > 其他分享 >金铲铲S13双城之战自动拿牌助手2.0

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

时间:2024-12-22 19:28:58浏览次数:5  
标签:yctb 金铲 thumb S13 self ocr print 2.0 stage

金铲铲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()

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

标签:yctb,金铲,thumb,S13,self,ocr,print,2.0,stage
From: https://blog.csdn.net/weixin_40967156/article/details/144638499

相关文章

  • Meld 代码比较分析软件Ubuntu22.04尝试
    直接官网下载,linux版本就可以,在执行时提示kairuszhang@kairuszhang:~/下载/meld-3.22.2/bin$./meldMeldrequiresGtkSourceView4.0orhigher.GLib-GIO-Message:23:02:19.773:AddingGResourcesoverlay'/org/gnome/meld=/home/kairuszhang/下载/meld-3.22.2/meld/reso......
  • Ubuntu 22.04LTS后,配置编译工具build-essential(输入sudo apt install build-essentia
    kairuszhang@kairuszhang:~$sudoapt-getinstallbuild-essential正在读取软件包列表...完成正在分析软件包的依赖关系树...完成正在读取状态信息...完成有一些软件包无法被安装。如果您用的是unstable发行版,这也许是因为系统无法达到您要求的状态......
  • OAuth2.0中刷新令牌(Refresh Token)的作用
    来着ChatGPT:1.为什么需要刷新令牌?访问令牌的短有效期:访问令牌(AccessToken)通常设置短有效期(例如几分钟到几小时),以减少令牌被盗用后产生的安全风险。令牌过期后,客户端需要一种方式重新获取新的访问令牌,以继续访问受保护资源。避免频繁授权:如果每次访问令牌过期后都需要......
  • 【全网首发】Ubuntu-22.04服务器系统搭建深度学习环境,安装cuda和cuDNN,并实现cuda灵活
    一、前言        截止2024年12月19日,所有搜索引擎中无法找到在服务器环境下搭建Ubuntu-22.04的cuda环境教程中文文章,并且许多安装教程已经过时、存在错误,使很多人走了弯路,因此发布本篇文章来造福社会。为编写本文耗费了近一周的时间尝试、整理,因此本文处处存在十分微......
  • 自研tauri2.0-vue3-os桌面端仿macos系统|Vite6+Tauri2.x+Arco管理os平台
    原创倾力之作Tauri2.0+Vite6+Vue3+ArcoDesign桌面版os管理系统。vue3-tauri2-macos基于最新跨平台框架tauri2.x整合vite6构建工具搭建桌面端os管理平台系统。支持macos和windows两种桌面风格,自研拖拽式桌面栅格引擎,封装tauri2高复用多窗体管理。技术栈编辑器:vscode技......
  • PortQry 命令行端口扫描程序版本 2.0 下载 PortQryV2.exe,这是一个命令行实用程序,可
    从Microsoft下载中心下载PortQry命令行端口扫描程序版本2.0---DownloadPortQryCommandLinePortScannerVersion2.0fromOfficialMicrosoftDownloadCenter使用PortQry命令行工具-WindowsServer|MicrosoftLearn 什么是PortQry?PortQry是一款由微软开......
  • Introducing Gemini 2.0: our new AI model for the agentic era
    IntroducingGemini2.0:ournewAImodelfortheagenticerahttps://blog.google/technology/google-deepmind/google-gemini-ai-update-december-2024/#ceo-message Gemini2.0FlashGemini2.0Flashbuildsonthesuccessof1.5Flash,ourmostpopularmod......
  • 关于 Sysprep、小鱼儿yr系统封装优化设置辅助工具、全自动系统封装工具 v5.5.3.6、系
    关于Sysprep、小鱼儿yr系统封装优化设置辅助工具、全自动系统封装工具v5.5.3.6、系统封装助手v2.0正式版、EasySysprep5Plus和系统封装首席执行官的对比分析表格,主要从功能、自动化程度、适用场景等角度进行比较。工具名称Sysprep小鱼儿yr系统封装优化设置辅助工具......
  • C#/.NET/.NET Core技术前沿周刊 | 第 17 期(2024年12.09-12.15)
    前言C#/.NET/.NETCore技术前沿周刊,你的每周技术指南针!记录、追踪C#/.NET/.NETCore领域、生态的每周最新、最实用、最有价值的技术文章、社区动态、优质项目和学习资源等。让你时刻站在技术前沿,助力技术成长与视野拓宽。欢迎投稿、推荐或自荐优质文章、项目、学习资源等......
  • 【教学类-83-02】20241214立体书三角嘴2.0——青蛙(扁菱形嘴)
    背景需求:制作小鸡立体贺卡三角嘴,它的嘴是正菱形(四条边长度相等,类似正方形)【教学类-83-01】20241215立体书三角嘴1.0——小鸡(正菱形嘴)-CSDN博客文章浏览阅读744次,点赞22次,收藏11次。【教学类-83-01】20241215立体书三角嘴1.0——小鸡(正菱形嘴)https://blog.csdn.net/reasonsum......