I'm writing a rhythm game in Java; right now I've reached the point where I'm trying to implement a metronome object.
I've coded a data structure that stores 8 channels of music data into a single QuarterBeat object; these are in turn stored in groups of 64 to make 4-measure 'chunk' objects.
To keep things synchronized properly I wanted to use a pair of parallel threads: one runs through the various events that happen at every quarter-beat before stopping on a 'wait()' method, while the other waits an amount of time derived from the BPM before signaling the first.
This is the code for the thread doing the work.
public class InGame {
public static boolean gameRunning = false;
public static boolean holdChunk = false;
public static boolean waiting = false;
public static ArrayList<Player> players = new ArrayList<Player>();
public void startUp() throws InterruptedException{
Parser.loadSamples();
for (int p = 0; p < Player.voicePool.size(); p++) {
Player makePlay = new Player();
makePlay.setChannel(p);
players.add(makePlay);
}
LevelStructure.SongBuild();
Metro timer = new Metro();
gamePlay(timer);
gameEnd();
}
synchronized public void cycle(Metro timer) throws InterruptedException{
int endPoint = LevelStructure.getChunkTotal();
for (int chunk = 0; chunk < endPoint; chunk++){
LevelStructure.setActiveChunk(chunk);
for (int quartBeat = 0; quartBeat < 64; quartBeat++){
synchronized (this){
new Thread(timer.ticking(this));
Player.getNewNotes(LevelStructure.getQuartBeat(quartBeat));
players.get(0).playback(LevelStructure.getQuartBeat(quartBeat));
waiting = true;
while (waiting) {
wait();
}
}
}
if (holdChunk) chunk--;
}
}
}
And the code for the Metro object:
public class Metro {
public static int BPM;
synchronized public Runnable ticking(InGame parent) throws InterruptedException{
synchronized (parent) {
Thread.sleep(15000/BPM);
InGame.waiting = false;
parent.notifyAll();
}
return null;
}
}
Right now it's throwing an Illegal Monitor State exception every time I try to run it; I've tried researching proper implementation of wait()/notify() on my own, but I'm still fairly new to Java and I can't find an explanation of handling parallel threading that I can understand. Do I need to invoke both the Cycle and Metro threads from a parent process?
Edit: Updated code: the issue now is that, instead of actually running in parallel, the Cycle object waits for the timer.ticking method to execute, then performs the actions it's supposed to do while Metro is sleeping, then gets stuck waiting for a notify that will never come. Which means that the threads aren't actually executing parallel to one-another.