What is the best way to time individual notes and chords?

Discussion in 'Plugin Development' started by pop4959, May 7, 2014.

Thread Status:
Not open for further replies.
  1. Offline

    pop4959

    I was wondering if there is some easy way to schedule noteblock notes in bukkit's API, and/or java. I would like to implement a song in MineCraft with code, which will need to be fairly carefully timed.

    If there is no better way to do this than the bukkit scheduler, please tell me. Examples or links would be much appreciated, as I am still fairly new to Java and Bukkit's API.
     
  2. Offline

    Drkmaster83

    I honestly have found no way to do this other than to create an Array or ArrayList and iterate through it, playing the note that the Iterator is on every time the scheduler is ran. I'm very interested as to any other answers for this, though, as this way is very ugly and no doubt inefficient.

    There's some sort of implementation with .MIDI song files (I thought so, at least), but not every song is a .MIDI.
     
  3. Offline

    coasterman10

    Bukkit's scheduler is going to be the most accurate way to do this short of using an asynchronous thread that sends packets to players on its own, which would introduce thread safety issues.
     
  4. Offline

    pop4959

    Hm, seems pretty messy. I quickly googled plugins relating to MIDI files, and there seem to be a few. Apparently it is possible, but as you said, not everything is available for MIDI. My intentions were to write some new and/or existing tunes for a server lobby. Thanks, :D

    I've been hoping to hear the opposite, but I suppose that's just the sad truth. Manually timing everything will take quite some time. Thanks you! :)

    If anyone has any other tips or tricks to getting this done better, please do tell. I still don't want to believe that the bukkit scheduler is the best thing there's going to be for note timings.
     
  5. Offline

    Rocoty

    You will probably have to use the BukkitScheduler for scheduling and timing. But if you design this cleverly you may only have to write the task once, and adding/removing/managing may be really easy. It is all about how you design it. Code design is important. So you would have to make good use of the OOP concepts at hand.
     
  6. Hendrik_the_best I really hope you didn't mean to use the word "class" there. Come to think of it, nor "Theart".
     
  7. Offline

    pop4959

    Sorry if I'm asking too much, but I haven't been able to figure out how to play through the array of notes, and time it. I'm pretty new to java, so I've only done a thing or two with the schedulers and arrays, not to mention both.

    Maybe someone can point out some fixes? This is what I have right now, but I know for a fact it's far from working at all. I've been able to play single notes thus far. Yeah no, I happened to have deleted it already, but I hadn't remembered doing so. Not going to rewrite bad code twice. So this is generally what I had (which didn't work):

    -Defined all notes
    -Define array of notes (not sure whether array or arraylist is better for this)
    -Scheduler, set to play the first note in the index, and increment.

    Maybe someone can give me a pointer..
     
  8. Offline

    tryy3

  9. Offline

    Drkmaster83

    Here's my personal code that I used to play Beethoven's 'Für Elise" in Minecraft.

    List (of notes, spaces are eighth rests, I believe):
    Code:
    List<String> elise = Arrays.asList("EHigh", "D#High", "EHigh", "D#High", "EHigh", "BHigh", "DHigh", "CHigh", "AHigh", " ", " ", "C", "E", "AHigh", "BHigh", " ", " ", "E", "G#High", "BHigh", "CHigh", " ", " ", " ", "EHigh", "D#High", "EHigh", "D#High", "EHigh", "BHigh", "DHigh", "CHigh", "AHigh", " ", " ", "C", "E", "AHigh", "BHigh", " ", " ", "EHigh", "CHigh", "BHigh", "AHigh", " ", " ", "CHigh", "CHigh", "DHigh", "EHigh", " ", " ", "CHigh", "FHigh", "EHigh", "DHigh", " ", " ", "GHigh", "EHigh", "DHigh", "CHigh", " ", " ", "AHigh", "DHigh", "CHigh", "BHigh", " ", " ", " ", "EHigh", "D#High", "EHigh", "D#High", "EHigh", "BHigh", "DHigh", "CHigh", "AHigh");
    
    Playing the song to a player (in my case, who did a command):
    Code:
    new BukkitRunnable() {
        Iterator<String> note = elise.iterator();
        String notePlayed = " ";
        @Override
        public void run() {
            if (note.hasNext()) {
                notePlayed = note.next();
                NoteUtils.playPianoNote(event.getPlayer(), notePlayed);
            }
            else {
                note = elise.iterator();
                cancel();
            }
        }
    }.runTaskTimer(plugin, 0L, 5L); //5 ticks repeating is approximately 240 BPM, which I had to use since I have to account for eighth notes. The formula ((20 / ticks) * 60) should give you the BPM, though to get an actual floating-point tick amount to run for a specific BPM, you can use 20 / (tempo / 60) (I believe).
    
    NoteUtils' "playPianoNote()" method, the method that plays notes
    Code:
    //variable 'skip' is an Integer, however, it was added much later, so if you use it, declare it as a class variable or whatnot to keep the data... I personally haven't tested this method in a while, but it worked well when I did.
    public static void playPianoNote(Player p, String note) {
        if(note.equalsIgnoreCase(" ") || note.equalsIgnoreCase("")) return;
        if(note.equalsIgnoreCase("  ")) skip = 1;
        if(note.equalsIgnoreCase("  ")) skip = 2;
        if(note.equalsIgnoreCase("    ")) skip = 3;
        if(skip > 0) {
            skip--;
            return;
        }
        p.playSound(p.getLocation(), Sound.NOTE_PIANO, 1f, Note.getNote(note).pitch);
    }
    
    Note enum that is used in NoteUtils
    Hidden because of a whole class

    Code:
    public enum Note
    {
        WHOLE_REST("    ", 0.0F),
        HALF_REST("  ", 0.0F),
        QUARTER_REST("  ", 0.0F),
        EIGHTH_REST(" ", 0.0F),
        F_SHARP("F#", 0.5F),
        G("G", 0.53F),
        G_SHARP("G#", 0.56F),
        A("A", 0.6F),
        A_SHARP("A#", 0.63F),
        B("B", 0.67F),
        C("C", 0.7F),
        C_SHARP("C#", 0.76F),
        D("D", 0.8F),
        D_SHARP("D#", 0.84F),
        E("E", 0.9F),
        F("F", 0.94F),
        F_SHARP_H("F#High", 1.0F),
        G_H("GHigh", 1.06F),
        G_SHARP_H("G#High", 1.12F),
        A_H("AHigh", 1.18F),
        A_SHARP_H("A#High", 1.26F),
        B_H("BHigh", 1.34F),
        C_H("CHigh", 1.42F),
        C_SHARP_H("C#High", 1.5F),
        D_H("DHigh", 1.6F),
        D_SHARP_H("D#High", 1.68F),
        E_H("EHigh", 1.78F),
        F_H("FHigh", 1.88F),
        F_SHARP_L("LastF#", 2.0F);
     
        String note;
        float pitch;
     
        Note(String note, float pitch) {
            this.note = note;
            this.pitch = pitch;
        }
     
        public float getPitch() {
            return this.pitch;
        }
     
        public static float getPitch(String note) {
            for (Note notePitch : values()) {
                if (notePitch.note.equalsIgnoreCase(note)) {
                    return notePitch.pitch;
                }
    }
    return 0.0F;
        }
     
        public static Note getNote(String note) {
            for (Note notePitch : values()) {
            if (notePitch.note.equalsIgnoreCase(note)) {
                    return notePitch;
                }
            }
            return null;
        }
    }
    
     
  10. Offline

    pop4959

    I do not think I am trying to play a song forever, but if I did, I would try to use that.

    This is an excellent example! Although I'm very busy with exams currently I'll try to use similar techniques in order to make my song work when I get the chance. I already have many notes defined, and part of the song complete, but I was unsure on how to time them in an efficient way in Bukkit. Thank you so much!
     
Thread Status:
Not open for further replies.

Share This Page