1

I am trying to animate my game in Java using the code below in a subclass of JComponent, but this code causes lags and jitters in the animation, and objects appear to be "split" as they are redrawn rapidly on the screen. How can I resolve this issue? Should I redraw each item on a separate thread?

public GameScene(){
   setDoubleBuffered(true);
   run();
}

...
public void run() {
    Thread animation = new Thread(new Runnable() {
        public void run() {
            updateGraphics();
        }
    });

    animation.start();
}

public void updateGraphics() {
    while (true) {
        repaint();

        try {
            Thread.sleep(5);
        } catch (Exception ex) {

        }
    }
}
Braj
  • 46,415
  • 5
  • 60
  • 76
Jack Humphries
  • 13,056
  • 14
  • 84
  • 125
  • Please share minimal testable code. – Braj May 16 '14 at 17:57
  • @Braj Well, all I have in the paintComponent method is standard code that changes the location of objects and then redraws them. There is nothing special. I feel that the code I posted above is fragile and may be problematic. The code is relying on the system to keep track of time, and the system doesn't seem to be able to count 5 milliseconds well. Is there a better way of calling the repaint() method? – Jack Humphries May 16 '14 at 17:59
  • What's the reason of calling Thread.sleep() with just 5 milli? – almanegra May 16 '14 at 18:04
  • @Miller 5 milliseconds seemed like an acceptable amount of time for the system to wait before redrawing the scene again. The animation seems realistic when this amount of time is used. – Jack Humphries May 16 '14 at 18:05
  • Have a look at this post [Simple Java animation with Swing](http://codereview.stackexchange.com/questions/29630/simple-java-animation-with-swing) – Braj May 16 '14 at 18:05
  • If your animation is very graphics-intensive, consider a Swing alternative like JavaFX. – Daniel May 28 '14 at 21:38

2 Answers2

3

Instead of using Java Timer try with Swing Timer that is more suitable for Swing application.

Please have a look at How to Use Swing Timers

Here is the sample code:

int delay = 1000; //milliseconds
ActionListener taskPerformer = new ActionListener() {
  public void actionPerformed(ActionEvent evt) {
      //...Perform a task...
  }
};
new Timer(delay, taskPerformer).start();

Find a Sample code here

enter image description here

Braj
  • 46,415
  • 5
  • 60
  • 76
2

You describe your issue pretty vaguely.

In principle, Swing isn't all that well suited for animation - speed isn't the principal problem - rather its the lack of a possibility to control when exactly the graphics are updated on screen.

Swing does not synchronize rendering with screen refresh. While it does double buffer (by default), it can (and does) still happen that the graphics are refreshed while the screen is displayed, displaying (for example) in the top half of the component frame N, while frame N+1 in the lower half (because the frame update happened while the screen refresh was somewhere in the middle of the screen).

The only solution I know of is switching to full screen mode (http://docs.oracle.com/javase/tutorial/extra/fullscreen/), where rendering may be beam synchronized. There is no solution for windowed display (to my knowledge).

Durandal
  • 19,919
  • 4
  • 36
  • 70