I'm making a reaction time application and I need to display this in the GUI so I need to use a Timeline to do this. I have made everything work with the Timeline, other than allowing the time between KeyFrames to be variable.
In the code below, I managed to make it change after the first KeyFrame (so there is no wait, and then a wait time of 'waitTime' seconds). It then uses the value of 'waitTime' and keeps the time between KeyFrames constant from here. In the code is what I am doing to change the variable 'waitTime'. I am just unsure how I can change the KeyFrame time. I think I need a recursive way of doing this but have not yet been able to find anything anywhere on this topic.
double waitTime;
Timeline attackChanger = new Timeline(new KeyFrame(Duration.ZERO, new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event){
//randomly generate attack
if(isCountdown = true){
int randI = rand.nextInt(10);
waitTime = randI;
System.out.println(waitTime);
String attack = utils.getRandomAttack();
attackLabel.setText(attack);
}
}
}), new KeyFrame(Duration.seconds(waitTime)));
Thank you in advance for any answers :)
After you start the Timeline
the KeyFrame
s are fixed. Even if they were not there's no passing of primitive types by reference in java, i.e. Duration.seconds(waitTime)
returns a Duration
object with constant duration no matter what you do to waitTime
later. While the animation is running modifying the list of KeyFrame
s does not have any effect either.
The probably best way of going about this would be to adjust the rate
property of the timeline according to the new value.
Assuming you use
attackChanger.setCycleCount(Animation.INDEFINITE);
on your animation:
Timeline attackChanger = new Timeline();
attackChanger.getKeyFrames().addAll(new KeyFrame(Duration.ZERO, new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event){
//randomly generate attack
if(isCountdown = true){
int randI;
// we need treat 0 immediately to avoid
// setting the rate to infinity
// note: in this case only a single
// text value will be displayed and you probably should
// go with (rand.nextInt(9) + 1) to generate values between
// 1 and 9 (inclusive)
// I keep it this way though because of the console output
// and possible side effects of utils.getRandomAttack()
do {
randI = rand.nextInt(10);
waitTime = randI;
System.out.println(waitTime);
String attack = utils.getRandomAttack();
attackLabel.setText(attack);
} while (randI == 0);
// (effective cycle duration) = (standard duration) / rate
attackChanger.setRate(1d / randI);
}
}
}), new KeyFrame(Duration.seconds(1)));
attackChanger.setCycleCount(Animation.INDEFINITE);
//make sure `waitTime` is not 0 at this point
attackChanger.setRate(1d / waitTime);