I have an animation in a JPanel that updates itself through a javax.swing.Timer. This timer can be constructed to have a delay in milliseconds that must be an integer. If I were to have the JPanel update 60 times each second, I would set the delay to 1000/60 = ~16.6666. However, this delay must be an int, so I have the option of rounding up or down. For a delay of 16 milliseconds, the animation would update at 62.5 frames per second. Rounding up to 17 millisecond delay would give a frame rate of 58.824.
How would I go about having a frame rate of exactly 60 frames per second?
Thanks in advance.
I see two options which could help you. They ultimately achieve the same thing in the same way, but the code is more or less general. I haven't found any tool out there that does the job for you, so it requires a little bit of work.
The first option is to do something like this:
/**
* Called by the timer when the next iteration is due. Assume that
* this happens at the right moment.
*/
public void onTimerUpdate() {
updateAnimation();
// Compute the next point in time that corresponds to the
// frame rate you want.
long nextScheduledTimestamp = getNextTimestampInNanos();
long nanos = System.timeNanos();
timer.schedule(task, convertToMillis(nextScheduledTimestamp - nanos));
}
The second option is for you to get your copy of java.util.Timer: http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/Timer.java
and rewrite the bits that are millisecond-specific. Nothing in its implementation in OpenJDK shows that its resolution is millisecond specific, so you should be able to replace Object.wait(millis)
calls with Object.wait(millis, nanos)
:
https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#wait(long,%20int)
Interesting article, just for fun: https://blogs.oracle.com/dholmes/entry/inside_the_hotspot_vm_clocks