使用Java实现在原神内自动弹琴

文章目录

    • 前言
    • 正文
      • 构思大概的逻辑与代码
    • 总结

前言

原神长草期,闲的无事便想试试里面的弹琴,奈何手残党,只能观望大佬的操作。但是,在我突发奇想下就想试试能否以我的能力使用代码将其自动化。

其实弹琴也就是掌握弹琴的按键和按下的时机即可,所以,理论上来说是比较简单的。

正文

首先,需要弹奏一首曲子,首先需要一个曲谱,这个可以在b站上找到很多热心的大佬会给出弹奏的曲子的曲谱。如下:
使用Java实现在原神内自动弹琴_第1张图片
这个是我找b站上找到的尤拉的浪沫之舞的弹奏按键(PC)。

构思大概的逻辑与代码

  1. 创建一个曲谱(就是一个普通的类)来保存这首曲子的弹奏条件,包括按键和各个按键按下的时机
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;
    }
}

  1. 创建一个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

你可能感兴趣的:(码代码,笔记,Java,java,玩游戏,程序人生,其他)