views:

83

answers:

4

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.

+4  A: 

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."

M. Jessup
+3  A: 

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.

trashgod
Thanks - I am already using Timer but want to move away from it as I'm concerned that a given machine won't be able to keep up with the specified frame rate; i.e. I want the machine to determine the frame rate rather than mandating it.
Adamski
I see, although I tend to think too narrowly in terms of a "render budget" based on the slowest target platform. I've added a related example that may offer some insight. @Jim Blackler's advice may be the best.
trashgod
U shld see Adamski's hot graphics. Theyd blow ur mind
oxbow_lakes
@oxbow_lakes: I'd love to; can you suggest a link?
trashgod
+1  A: 

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.

pajton
Thanks - I'll check it out.
Adamski
A: 

I would use an animation library for doing the animation instead of reinventing the wheel. Here are two good choices:

Jay Askren