I am writing a simulation in Java whereby objects act under Newtonian physics. An object may have a force applied to it and the resulting velocity causes it to move across the screen. The nature of the simulation means that objects move in discrete steps depending on the开发者_如何学运维 time ellapsed between the current and previous iteration of the animation loop; e.g
public void animationLoop() {
long prev = System.currentTimeMillis();
long now;
while(true) {
long now = System.currentTimeMillis();
long deltaMillis = now - prev;
prev = now;
if (deltaMillis > 0) { // Some time has passed
for (Mass m : masses) {
m.updatePosition(deltaMillis);
}
// Do all repaints.
}
}
}
A problem arises if the animation thread is delayed in some way causing a large amount of time to ellapse (the classic case being under Windows whereby clicking and holding on minimise / maximise prevents a repaint), which causes objects to move at an alarming rate. My question: Is there a way to determine the time spent in the animation thread rather than the wallclock time, or can anyone suggest a workaround to avoid this problem?
My only thought so far is to contstrain deltaMillis
by some upper bound.
Have you considered using something like a timer instead of spinning in a loop?
TimerTask tt = new TimerTask(){
long prev = System.currentTimeMillis();
public void run(){
long now = System.currentTimeMillis();
for (Mass m : masses) {
m.updatePosition(now-prev);
}
prev = now;
}
}
new Timer(true).schedule(tt, 1000, 1000) ;
This way you are guaranteed to at least have some delay between the update of your objects so you shouldn't have a bunch of repaints consecutively as with the while(true) loop, and if the thread is delayed you will not got an immediate re-execution of the task, from the docs: "In fixed-delay execution, each execution is scheduled relative to the actual execution time of the previous execution."
I found javax.swing.Timer.html
particularly helpful for this. Here's an example that models elastic collisions among spherical particles and the walls of a container.
Addendum: This related approach may help de-couple the model from the view. A separate thread models the system's evolution, while the view renders a "snapshot" of the model at a fixed rate.
In either case, I cap the rate to accommodate the slowest target platform.
You might like to read this article entitled "Java: Getting Thread Time with ThreadMXBean".
Basically, there is a class ThreadMXBean that enables you to get time spent in particular Thread
. I haven't tried that, but the methods (and examples from article I mentioned) look promising, so I think you will be able to accomplish what you want with this.
I would use an animation library for doing the animation instead of reinventing the wheel. Here are two good choices:
- The Timing Framework
- Trident
精彩评论