1

I got a simple 2D game in Java. The chararcters on the screen are controlled using Key Bindings. The game uses a class that extends JPanel, to display the graphics and contain most of the game logic. This class' name is Board.

What type of game loop should I use to every 40 milliseconds the game and repaint() the Board?

Option A:

Board contains a thread that starts when the program starts. This thread contains a loop that once in 40 ms updates the game and repaints() Board.

Option B:

Board creates a Swing timer. This timer's action listener is Board itself. The actionPerformed() method runs every 40 ms and updates the game + repaints Board().

In other words, in a 2D game with Key Bindings, what's better for the game loop and why - Swing timer or a thread with a loop inside it?

Thanks

user3150201
  • 1,901
  • 5
  • 26
  • 29

3 Answers3

2

If the processing is quick and your changes involve more interaction with Swing than just repaint() then a SwingTimer would be appropriate as you will already be on the correct thread.

Reasons: SwingTimer is quick, you don't need thread switches to update Swing - but the UI is frozen while you are processing so if you need any time players will notice.

If the processing might take some time and you need Swing interaction then use a SwingWorker.

Reasons: Swing worker is set up to handle the passing of messages back and forth between Swing and a worker thread for you.

Otherwise use a ScheduledExecutorService and scheduleAtFixedRate (which will mean you are called every 40ms even if your processing takes 0, 5, 10 or 20ms). The repaint() method is safe to call from off the EDT.

Reasons: ScheduledExecutorService is the standard way for scheduling tasks to be executed in Java. It handles once off and repeated execution and it will keep your updates consistently paced even if your execution times vary (so long as you don't take more than 40ms). You can call repaint() from any thread so you have no extra thread synchronization to worry about.

As a side note, this architecture is fine for a simple game, but you should consider that in a more complex game updates may take longer than 40ms and think of ways to compensate.

Tim B
  • 40,716
  • 16
  • 83
  • 128
  • +1 for Swing Timer, `The repaint() method is safe to call from off the EDT.` couldn't be true in Java7, because there were removed all Thread Safe methods valid for <= Java6, is required to test by using isEventDispatchThread – mKorbel Jan 03 '14 at 14:02
  • I wasn't aware of that. Do you have a link to an official reference for this? I just tried googling and got some discussion but nothing concrete. – Tim B Jan 03 '14 at 14:07
  • yes you can to compare (start with) JTextComponents.append/setText ... a few times mentioned here – mKorbel Jan 03 '14 at 14:14
  • Discussion of repaint here: http://stackoverflow.com/questions/20905985/is-swing-repaint-still-thread-safe-in-java-7 – Tim B Jan 03 '14 at 18:27
0

Use two threads one for repainting and one or more for the motion of objects. No sure why you would need to synchronize between them, they could work independently.

alex
  • 301
  • 3
  • 13
0

If the only moving things on screen are the characters controlled by keys (using keyBindings) I believe you could successfully repaint the screen only when a character is moved, so the movement method could call repaint at the end. I tried it myself for some simple projects and that worked fine. Just every moving object would call repaint after it moved.

In one of the projects (really simple one) I called repaint inside actionPerformed for the keyBinding, it looked like this:

class Right extends AbstractAction{
    @Override
    public void actionPerformed(ActionEvent e){
        if (board.character.x < 465){    //check if not trying to move off the screen.
        board.character.x += 7;
        board.repaint();
        }
    }
} 
3yakuya
  • 2,622
  • 4
  • 25
  • 40
  • That's very cheap, but there is no game loop here. Its like you are repainting a component. He said 40 millis, 25fps per loop. – alex Jan 03 '14 at 17:03