基于pyautogui的自动识别定位原神风物之诗琴按键弹奏程序

news2025/1/13 2:51:49

前言:

为了学习pyautogui这个库的使用,我准备用它做点东西。比如一个自动弹琴的程序。

不过这个琴不是现实里的琴,而是原神里的风物之诗琴。(这里有个网页版模拟器可以试试:风物之诗琴模拟器 (haveyouwantto.github.io))

功能需求:

因为我们要让程序自动弹奏的是游戏里的琴,所以我们这个程序需要基于pyautogui库实现一下几个主要的功能:

  1. 识别屏幕上各个琴键的位置

  1. 读取以特定格式编好的琴谱

  1. 根据琴谱正确按下特定按键

那下面就开始制作呗!

一、琴键识别

我们要弹的琴的界面是这样的:

简单分析一下:它有低中高(分别对应下中上)三行,每一行都是do-ti。所以比如识别do的话会识别出三个位置,那只需要根据垂直坐标大小进行区分即可。

然后制作一份音调和对应琴键图存储路径的配置表:

截好图:

然后读取配置信息和图片,定位琴键。。。。。。

好,停!

代码测试到一半的时候,我就明白了这个定位方法并不好用。因为我想尽可能适应不一样的游戏窗口大小,所以会适当降低匹配的精度,但是这样就会导致很多匹配的错误,可能匹配某个音匹配了不止三个。。。只要没办法精确区分每个音调的位置,就没办法完成弹奏的任务。

那我们重新分析一下这个弹琴面板:

从中可以看出,最左边一列标志上下相邻的距离,和标志与其右边do音符的距离相等,同时这个距离也和音符键的左右相邻距离很相近。那我们就有了下面这个新策略(假定左上角为坐标原点,向右为x正方形,向下为y正方向):

  • 获取标志1的中心位置L1(x1,y1):

  • 获取标志2的中心位置L2(x2,y2):

  • 计算L1和L2的距离d,则第一行各个音符的点击坐标为(x1+d,y1),(x1+2d,y1),(x1+3d,y1)......

第二行各个音符的点击坐标为(x1+d,y1+d),(x1+2d,y1+d),(x1+3d,y1+d)......

第三行各个音符的点击坐标为(x1+d,y1+2d),(x1+2d,y1+2d),(x1+3d,y1+2d)......

那没必要配置文件了,直接干!

上代码!:

import pyautogui
import math
import time

locations = [] #从左到右从上到下存储各个按键的位置 一共3*7=21个

L1_img = "0.png"
L2_img = "1.png"

#L1 = L2  = d = None
while(True):
    input("按回车键开始定位")
    L1 = pyautogui.locateCenterOnScreen(L1_img,confidence=0.87)
    L2 = pyautogui.locateCenterOnScreen(L2_img,confidence=0.87)
    if(L1 !=None and L2 !=None):
        print("定位完成!")
        break
    else:
        print("定位失败")
d = L2.y - L1.y
if(d < 0):
    print("定位距离异常!")
    exit(0)
for i in range(3):
    for j in range(1,8):
        locations.append(pyautogui.Point(L1.x+d*j,L1.y+d*i))
for l in locations:
    pyautogui.click(l)

运行效果:

二、编写琴谱

首先定义一下映射规则:

把各个音和对应的按键位置列表下表映射起来。(比如0mi就是第0行的mi)

然后我们根据规则编个谱子(《晴天》的前一小段)(*表示休止符,空格或回车隔开各个音):

三、运行测试

脚本先定位琴键位置,然后读取谱子,然后根据谱子按下对应的按键进行自动弹奏:

import pyautogui
import math
import time

locations = [] #从左到右从上到下存储各个按键的位置 一共3*7=21个

L1_img = "0.png"
L2_img = "1.png"
puzi = "puzi.txt"

#琴键-位置下标 的映射
key_loc_map = {
    "0do":0,
    "0re":1,
    "0mi":2,
    "0fa":3,
    "0so":4,
    "0la":5,
    "0ti":6,
    "1do":7,
    "1re":8,
    "1mi":9,
    "1fa":10,
    "1so":11,
    "1la":12,
    "1ti":13,
    "2do":14,
    "2re":15,
    "2mi":16,
    "2fa":17,
    "2so":18,
    "2la":19,
    "2ti":20,
}

#L1 = L2  = d = None
while(True):
    input("按回车键开始定位")
    L1 = pyautogui.locateCenterOnScreen(L1_img,confidence=0.9,grayscale=True)
    L2 = pyautogui.locateCenterOnScreen(L2_img,confidence=0.9,grayscale=True)
    if(L1 !=None and L2 !=None):
        print("定位完成!")
        print(L1)
        print(L2)
        break
    else:
        print("定位失败")
d = L2.y - L1.y
if(d < 0):
    print("定位距离异常!")
    exit(0)
for i in range(3):
    for j in range(1,8):
        locations.append(pyautogui.Point(L1.x+d*j,L1.y+d*i))

def Play(pu_path,delta):
    p = open(pu_path,"r",encoding="utf-8")
    puzi = eval(p.read())
    for sound in puzi:
        if sound!="*":
            pyautogui.click(locations[key_loc_map[sound]])
        time.sleep(delta)
    p.close()

input("回车开始弹奏")

Play(puzi,0.15)

稍微测试一下(这个编辑器出了点问题视频就放连接了):

https://live.csdn.net/v/270125

运行没问题。

四、总结

虽然在上面的网页模拟器的测试中运行似乎挺好的,但是在实际应用到游戏中效果其实并不好,缺点如下:

1、首先,游戏中弹琴的时候,琴背景是在时刻变化的,所以导致所要定位的那小块区域的像素和截图的有所出入,导致检测不到或者检测不准。

2、然后编写琴谱太麻烦(我是另外用脚本把键盘谱转化为这里的音谱的)。

3、接着就是,由于这里的弹奏方式是按固定的时间间隔进行弹奏或者休止,所以音乐弹出来很机械,没法体现那种缓急变化感。如果对每个音设置时间间隔的话又导致谱子的编写难度陡增。

4、最后,因为这个弹奏的方式是模拟鼠标点击进行弹奏,虽然能同时适配模拟器的移动端原神和PC版原神,但是做不到同时弹两个音,所以就没办法很好地弹出和弦。

所以,这个程序做出来就是图一乐,再往下去很难有较大的提升空间。想做一个好点的自动弹奏程序的话要考虑新的琴键触发方式和琴谱组织形式。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/162896.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Spring 监听器listener原理

1.创建本地事件和事件监听器/*** 事件类*/ public class MyEventA extends ApplicationEvent {private static final long serialVersionUID 1L;public MyEventA(Object source) {super(source);System.out.println("MyEventA 构造方法被执行了...");}public void o…

基于matlab开发的车牌检测与字符分割项目附源码

文章目录1 任务概述项目完整matlab源码2 基本流程2.1 车牌定位2.1.1 图像预处理2.1.2 边缘检测2.1.3 形态学操作2.1.4 重操作判断2.1.5 区域选择2.1.6 倾斜校正2.1.7 精确选择2.2 字符分割2.3 字符识别3 结果分析3.1 车牌定位3.2 字符分割3.3 字符识别4 总结5 参考资料1 任务概…

安装vim的最新版本

1、通过源码安装 对于Linux系统&#xff0c;可以通过源码编译来安装最新版本&#xff0c;我在wsl ubuntu下的操作如下&#xff1a; 获取vim的源码&#xff1a; git clone https://github.com/vim/vim.git刚开始我帆了墙&#xff0c;结果下载不动&#xff0c;关了帆墙软件可正常…

【入门AUTOSAR网络管理测试】AUTOSAR网络管理规范需求解读

文章目录前言一、名词解释二、NM报文1.NM报文格式2.NM报文数据场内容三、NM状态机1.NM状态转换图2.状态前言 AUTOSAR Automotive Open System Architecture&#xff0c;汽车开放系统架构&#xff0c;由全球汽车制造商、部件供应商及其他电子、半导体和软件系统公司联合建立&am…

Qt扫盲-QPlainTextEdit理论总结

QPlainTextEdit理论总结一、概述二、用途一&#xff1a;纯文本展示1. 用法2. 只读快捷键三、用途二&#xff1a;纯文本编辑器1. 用法2. 快捷键绑定四、与 QTextEdit 的不同一、概述 QPlainTextEdit是一个只支持纯文本的高级查看器/编辑器。 它经过优化&#xff0c;可以处理大型…

Mac系统下matplotlib中SimHei中文字体缺失报错的解决办法

问题描述import matplotlib.pyplot as plt plt.rcParams[font.sans-serif][SimHei] plt.rcParams[axes.unicode_minus]False使用matplotlib画图时&#xff0c;因为缺少字体&#xff0c;、图像上label上的中文显示时空白小方块。因为matplotlib默认没有中文。解决方法&#xff…

多维时序 | MATLAB实现VMD-SSA-KELM和VMD-KELM变分模态分解结合麻雀算法优化核极限学习机多输入单输出时间序列预测

多维时序 | MATLAB实现VMD-SSA-KELM和VMD-KELM变分模态分解结合麻雀算法优化核极限学习机多输入单输出时间序列预测 目录多维时序 | MATLAB实现VMD-SSA-KELM和VMD-KELM变分模态分解结合麻雀算法优化核极限学习机多输入单输出时间序列预测预测效果基本介绍程序设计学习小结参考资…

城堡、游乐园、地下城!!!500+ 超棒 FBX 模型素材,全部都免费!

近期 Cocos 社区有好几位热心的开发者&#xff0c;整理了一些 CC0 协议 的游戏资源。如果你对 CC0 协议还不太了解&#xff0c;我找到一个中文版的协议说明&#xff0c;看下图&#xff1a;有几点比较重要&#xff1a;作者放弃著作权&#xff0c;已将作品贡献至公共领域可以复制…

【ROS】—— 机器人系统仿真 —RDF、Gazebo与Rviz综合应用(十六)

文章目录前言1. 机器人运动控制以及里程计信息显示1.1 ros_control 简介1.2 运动控制实现流程(Gazebo)1.2.1 为 joint 添加传动装置以及控制器1.2.2 xacro文件集成1.2.3 启动 gazebo并控制机器人运动2. 雷达信息仿真以及显示2.1 新建 Xacro 文件&#xff0c;配置雷达传感器信息…

C++STL之vector的模拟实现

由于vector和string的接口使用方法类似&#xff0c;这里便不再详细讲解vector各种接口的使用了&#xff0c;可以参考之前所发布的string的使用&#xff0c;或者从官方文档中获取详细的使用方法. 目录 vector介绍 构造函数&#xff08;有参&#xff0c;无参&#xff0c;迭代器…

【14】Docker network | bridge | host | none | container

目录 1、Docker 运行的基本流程为: 2、Docker0 3、Docker默认的三种网络模式 4、Docker的网络命令 5、网络模式 6、实例&#xff1a; 7、bridge模式 8、host模式 9、none模式 10、container模式 11、自定义网络 1、Docker 运行的基本流程为: 1.用户是使用 Docker Clie…

UDS诊断系列介绍10-28服务

本文框架1. 系列介绍1.1 28服务概述2. 28服务请求与应答2.1 28服务请求2.2 28服务正响应2.3 否定应答3. Autosar系列文章快速链接1. 系列介绍 UDS&#xff08;Unified Diagnostic Services&#xff09;协议&#xff0c;即统一的诊断服务&#xff0c;是面向整车所有ECU的一种诊…

session利用的小思路

session利用的小思路 前言 做题的时候经常考到session利用&#xff0c;常见的基本就两种&#xff0c;session文件包含和session反序列化&#xff0c;之前没有详细总结过&#xff0c;就写写吧。 session文件包含 php.ini session的相关配置 session.upload_progress.enabl…

15、ThingsBoard-自定义阿里云SMS规则节点

1、概述 一个物联网平台承载着很多设备的连接,当设备出现异常的时候,能够快速的通知到运维管理员是非常重要的,thingsboard提供了自定义配置邮箱,但是它对支持发送短信的不是很友好,都是国外的sms服务商,我反正是不用那个,在国内常见就是阿里、腾讯、华为、七牛常用的s…

CORBA,Common Object Request Broker Architecture 简介

CORBA&#xff0c;Common Object Request Broker Architecture 简介 1. 简介 CORBA&#xff08;Common ObjectRequest Broker Architecture&#xff0c;公共对象请求代理体系结构&#xff09;是由OMG组织&#xff08;OMG组织是一个国际性的非盈利组织&#xff0c;其职责是为应…

【17】Docker | CAdvisor_InfluxDB_Granfana | 成功安装

目录 1、查看目前docker容器的状态 2、三大组件 【1】、CAdvisor 【2】、InfluxDB 【3】、Granfana 3、用docker-compose安装三个组件 4、三大组件的登录 【1】浏览cAdvisor收集服务&#xff0c;http://ip:8080 【2】浏览influxdb存储服务&#xff0c;http://ip:8083 …

python日志处理模块讲解-loguru

说明&#xff1a; 本篇文章主要讲的是python日志模块loguru详解&#xff0c;感兴趣的同学赶快来看一看吧。 背景&#xff1a; 在部署一些定时运行或者长期运行的任务时&#xff0c;为了留存一些导致程序出现异常或错误的信息&#xff0c;通常会采用日志的方式来进行记录这些…

运放指标-压摆率SR

1. 压摆率SR 处理交流信号时&#xff0c;压摆率是运放器件重要的指标。其表示运放输出电压的转换速率。在高频信号时&#xff0c;若压摆率不够&#xff0c;则运放输出的信号会变形&#xff0c;导致不满足要求。其实际就是运放输出信号的分辨率&#xff0c;只有分辨率足…

机器学习中的数学基础(四):概率论

机器学习中的数学基础&#xff08;四&#xff09;&#xff1a;概率论4 概率论4.1 一些概念4.2 二维随机变量4.2.1 离散型4.2.2 连续型4.3 边缘分布4.3.1 离散型边缘分布4.3.2 连续型边缘概率密度4.4 期望4.4.1 一维期望4.4.2 二维期望4.5 马尔可夫不等式4.6 切比雪夫不等式在看…

Vue2.0开发之——组件数据共享-Eventbus(39)

一 概述 兄弟组件之间数据共享的方案—EventBusEventBus的使用步骤EventBus的使用示例 二 兄弟组件之间数据共享的方案—EventBus 在 vue2.x 中&#xff0c;兄弟组件之间数据共享的方案是EventBus。 三 EventBus的使用步骤 创建 eventBus.js 模块&#xff0c;并向外共享一…