Search code examples
javaswinggame-loop

Is using "SwingUtilities.invokeLater()" inside a Java game loop a bad practice?


So, I'm creating a isometric game in JAVA; to put it simply, it has a map made of tiles, and when the user drag the mouse on the screen, the map moves. To give you guys an idea, it currently looks like this:

Before the actual prototype version, I built a small java application that had no "Game Loop" per se; the only thing updating the tile-map position was the event listeners for the mouse dragging, and it called the repaint() method after the movement update. It worked fine, and I could select Tiles and move the map without a problem.

Since then, I rebuild the prototype thinking in developing something more like a real game engine, with a Game States Manager and a real Game Loop; the Game Loop code looks like this:

    init();

    long start;
    long elapsed;
    long wait;

    while(running){
        start = System.nanoTime();

        update();
        draw();
        drawToScreen();

        elapsed = System.nanoTime() - start;
        wait = targetTime - elapsed / 1000000;

        if(wait < 0)wait = 5;
        try{
            Thread.sleep(wait);
        } catch(Exception e) {
            e.printStackTrace();
        }

    }

A GameStateManager is acessed with the update() and draw() methods, so I can draw the map just fine, like the older prototype. The problem happened when I dragged the mouse on the screen so the map could move; the animation became VERY croppy, in the extent that I could actually see the black background between the tiles moving before the final position of all tiles.

At first I thought the problem was in a concurrency between the Game Loop thread and the event listeners of the main class, because the mouseDragged event could be called while the JPanel was trying to draw what the map was like a moment ago; then I tested this on my game loop code:

        SwingUtilities.invokeLater(new Runnable(){
            public void run(){
                draw();
                drawToScreen();
            }
        });
        //draw();
        //drawToScreen();

And now the prototype is working just fine.

So, my question is, is this performance heavy, or just a bad practice in Java? Also, was my "concurrency" assumption right? This is my first time dealing with threads in Java, so I don't really know if I dealed with the problem the right way.

obs: This is the entire class I made in which the game loop is in: http://pastebin.com/RMRHYc5X

obs2: If someone is interested, the game loop logic I worked in was based on a youtube java tutorial made by pj644 named "2D Game Programming in Java".

obs3: Sorry if the question became too big, this is my first time posting a question on this site!


Solution

  • Swing isn't really a great technology for writing games, it updates slowly and is quite limited in a number of ways.

    Having said that yes calling invokeLater or using a SwingWorker would be the correct way to update the screen when your game thread has done its work.

    Before you go too much further though I really suggest looking at a 2d or 3d java graphics and game framework. You will be able to get much better results that way and a lot of the work in terms of setting up the game loop, updates, managing frame rates, etc will be done for you.