文章目录
前言
原神长草期,闲的无事便想试试里面的弹琴,奈何手残党,只能观望大佬的操作。但是,在我突发奇想下就想试试能否以我的能力使用代码将其自动化。
其实弹琴也就是掌握弹琴的按键和按下的时机即可,所以,理论上来说是比较简单的。
正文
首先,需要弹奏一首曲子,首先需要一个曲谱,这个可以在b站上找到很多热心的大佬会给出弹奏的曲子的曲谱。如下:
这个是我找b站上找到的尤拉的浪沫之舞的弹奏按键(PC)。
构思大概的逻辑与代码
- 创建一个曲谱(就是一个普通的类)来保存这首曲子的弹奏条件,包括按键和各个按键按下的时机
package TestCode.Music;
public class Music2 extends AbstractMusic{
private int DELAY_Space = 250; //空格所需要的时间间隔ms
private int DELAY_None = 150; //表示连续的按下时间间隔ms
private int DELAY_Same = 0; //表示按键同时按下ms
//尤拉的浪沫之舞
private String music = "N EEE W Q (JB) Q W J G V " +
"EEE W Q (JZ) Q T E (JZ)" +
"X X EE (EX) W X Q (JN) Q N W (JN) (GN) (HM)" +
"M (HM) J M Q" +
"(JC) (JC) (JC) (JC) C"
+
"(QV) A V A B S QW (JB) H S G (DN) D J (JN) D N D N D" +
"(QX) S (HX) S (DB) S QW (JB) H S G(HN) D E (EN) D" +
"(EN)(EN) W N (EN)" +
"(NX) DDD S A (MX) TU";
@Override
public int getDELAY_Space() {
return DELAY_Space;
}
@Override
public int getDELAY_None() {
return DELAY_None;
}
@Override
public int getDELAY_Same() {
return DELAY_Same;
}
@Override
public String getMusic() {
return music;
}
}
- 创建一个Analyze类,将输入的曲谱变成MusicPlay类可以识别的CD类.
CD类
package TestCode.CD;
import java.util.List;
public class CD {
private List<Integer> keyEvent; //存储按键
private List<Integer> delay; //存储按键之间的时间间隔
public List<Integer> getKeyEvent() {
return keyEvent;
}
public List<Integer> getDelay() {
return delay;
}
public void setKeyEvent(List<Integer> keyEvent) {
this.keyEvent = keyEvent;
}
public void setDelay(List<Integer> delay) {
this.delay = delay;
}
}
Analyze类
package TestCode.Utils;
import TestCode.Music.AbstractMusic;
import TestCode.CD.CD;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.List;
/**
* 用于识别曲谱
*/
public class Analyze {
private AbstractMusic musicScores;
private List<Integer> keyEvents;
private List<Integer> delays;
/**
* 将传入的乐谱进行解析为播放器可以播放的CD
* @param musicScores 传入的乐谱
*/
public Analyze(AbstractMusic musicScores) throws Exception {
this.musicScores = musicScores;
dealMusicScores();
}
/**
* @return 获得播放器可以处理的CD
*/
public CD getCD() {
CD cd = new CD();
cd.setKeyEvent(keyEvents);
cd.setDelay(delays);
return cd;
}
/**
* 对歌曲进行处理,转化为播放器可以处理的文件
*/
private void dealMusicScores() throws Exception {
keyEvents = new ArrayList<>();
delays = new ArrayList<>();
String music = musicScores.getMusic().trim(); //去除首位空格
music = music.toLowerCase(); //全部转换为小写
music = music.replace("\n", "");
for (int i = 0; i < music.length(); i++) {
char key = music.charAt(i);
if (Character.isLetter(key)) {
keyEvents.add(KeyEvent.getExtendedKeyCodeForChar(key));
delays.add(musicScores.getDELAY_None());
} else if (Character.isSpaceChar(key)) {
keyEvents.add(-1);
delays.add(musicScores.getDELAY_Space());
} else if (key == '(') {
key = music.charAt(++i);
while (key != ')') {
keyEvents.add(KeyEvent.getExtendedKeyCodeForChar(key));
delays.add(musicScores.getDELAY_Same());
key = music.charAt(++i);
}
} else {
// throw new Exception("error keyCode");
}
}
}
}
MusicPlay类(其中,MusicPlay类实现了DirectPlay类,可以直接传入乐谱进行播放)
package TestCode.MusicPlay;
import TestCode.CD.CD;
import TestCode.Music.AbstractMusic;
import TestCode.Utils.Analyze;
import TestCode.Utils.DirectPlay;
import TestCode.Utils.MusicPlay;
import TestCode.Utils.MusicScoresShow;
import java.awt.*;
import java.util.List;
/**
* 一代有音乐播放器
*/
public class MusicPlayer1 extends MusicPlay implements MusicScoresShow, DirectPlay {
private List<Integer> keyEvent;
private List<Integer> delay;
private int delayStart = 7 * 1000; //默认的音乐开始播放时间
@Override
public void showMusicScores() {
}
/**
* 进行音乐播放
*/
@Override
public void play() throws AWTException {
Robot robot = new Robot();
robot.delay(delayStart);
for (int i = 0; i < keyEvent.size(); i++) {
if (keyEvent.get(i) != -1) {
robot.keyPress(keyEvent.get(i));
robot.keyRelease(keyEvent.get(i));
}
robot.delay(delay.get(i));
}
}
/**
* 设置需要播放的CD
* @param cd 需要播放的CD
*/
@Override
public void setMusic(CD cd) {
this.keyEvent = cd.getKeyEvent();
this.delay = cd.getDelay();
}
/**
* 使用DirectPlay接口,直接传入乐谱进行播放
* @param musicScores 需要进行播放的乐谱
* @throws Exception
*/
@Override
public void musicPlay(AbstractMusic musicScores) throws Exception {
Analyze analyze = new Analyze(musicScores);
setMusic(analyze.getCD());
play();
}
/**
* 设置音乐开始播放的时间
* @param delayStart ms
*/
public void setDelayStart(int delayStart) {
this.delayStart = delayStart;
}
}
用于播放音乐的主函数使用
package TestCode;
import TestCode.Music.Music2;
import TestCode.Music.Music_zhou;
import TestCode.MusicPlay.MusicPlayer1;
import TestCode.Utils.Analyze;
import org.junit.Test;
import java.awt.*;
public class test1 {
public static void main(String[] args) throws AWTException {
try {
//使用第一种方式播放七里香
Analyze analyze = new Analyze(new Music_zhou());
MusicPlayer1 musicPlayer1 = new MusicPlayer1();
musicPlayer1.setMusic(analyze.getCD());
musicPlayer1.play();
} catch (Exception e) {
e.printStackTrace();
}
}
@Test
public void test2() {
//使用第二种方式播放浪沫之舞
try {
MusicPlayer1 musicPlayer1 = new MusicPlayer1();
musicPlayer1.setDelayStart(5 * 1000);
musicPlayer1.musicPlay(new Music2());
} catch (Exception e) {
e.printStackTrace();
}
}
}
总结
其实只要掌握了Java的Robot类就可以实现一些基本的自动化,以上的主要使用的也就是Robot类。
!!!
需要注意的是,在找到对应的曲谱后需要根据曲谱对应的节奏进行适当更改,也就是DELAY,延迟时间。
最后附上工程总文件,需要的自取,里面有七里香和另一首比较简单的,当然本人的音乐节奏不是很好,以上技术权当抛砖引玉了。
如有疑问,欢迎留言交流
链接:https://pan.baidu.com/s/1RL0yb-7PT1hoBYOEaWEaxA
提取码:hsim
或直接点击
原神弹琴
提取码:
hsim