Search code examples
javafor-loopjavafxdelaytimeline

Delay function does not work properly?


I am new to this community and I have a problem I can't seem to resolve on my own, not even when searching google and asking friends for answers.

I'm making a small pattern memorization game that revolves around clicking buttons in a certain sequence which would get harder each time you succeed, until you fail. The setup is via a javafx GUI and the IDE is NetBeans 8.1 .

Now, when a sequence is being displayed to the player via button glows for example, there needs to be a delay between each button and the next in the sequence in order for the player to know the order in which they'd click the buttons. There are three delay functions I've tried but all produce the same result, they are Thread.sleep , Timelines and Transitions.

Screenshot of the implementation of the delay section

As you can see in the above image, this for loop selects one of the 5 buttons in the game at random, and makes it glow so the player would know this is the next button in the sequence. All this occurs within a new timeline that is created on each iteration of the loop, so a delay should happen each time a button is selected and displayed.

However, what I'm seeing is quite weird when I execute this section of the code. The for loop exists inside a button event handler. When I click this button I do see a delay alright, but instead of between each button and the next in the sequence, I see the delay between the clicking of the button and the display of the entire sequence at once.

So how do I make this delay work as intended? From what I've heard Timeline is one of the best methods of implementing delays, as opposed to the unreliable Thread.sleep method which slows down your device a great deal when you execute the code.

For reference, first,second,third,fourth and fifth are the names of the buttons. The storebutton function stores the position of the current button for later reference in the game (you can ignore that sentence, it does not affect the implementation of the delay), borderglow is the button glow effect, and generator is the object from the Random class which generates a random integer between 0 and 5.

Please take your time in considering this problem, It's quite baffling and I can't work this one out. Try this idea in your IDEs even to understand the problem better. Any help would be greatly appreciated. My thanks in advance :)


Solution

  • Calling Timeline#play runs the Timeline, but immediately returns. You are effectively creating multiple separate timelines, and running them all almost at the same time.

    To achieve the desired effect you have a few options:

    1. Create a single timeline, add KeyFrames to it, each with successively higher time target:

      Timeline timeline = new Timeline();
      for (int i=0; i<buttoncount; i++) {
          timeline.getKeyFrames().add(new KeyFrame(Duration.millis((i+1)*1000), e -> {
              // Change highlighted button
          });
      } 
      timeline.play();
      

    This will create one Timeline with KeyFrames of target times 1000, 2000, 3000 ... milliseconds.

    1. Create a timeline with a single KeyFrame of a constant time, and run it multiple times:

      Timeline timeline = new Timeline(new KeyFrame(Duration.millis(1000), e -> {
          // This will be called multiple times, each time reset the highlighted button and select a new one to highlight
      }));
      timeline.setCycleCount(buttoncount);
      timeline.play();