正在使用" SwingUtilities.invokeLater()"在Java游戏循环中循环不好的做法?

时间:2014-07-22 08:58:41

标签: java swing game-loop

所以,我在JAVA创造了一个等距游戏;简单地说,它有一个由瓷砖组成的地图,当用户在屏幕上拖动鼠标时,地图会移动。为了给你们一个想法,它目前看起来像这样:

在实际的原型版本之前,我构建了一个没有" Game Loop"本身;更新tile-map位置的唯一方法是鼠标拖动的事件侦听器,并在移动更新后调用repaint()方法。它工作正常,我可以选择Tiles并毫无问题地移动地图。

从那时起,我重建原型思维,开发更像真实游戏引擎的东西,游戏状态管理器和真正的游戏循环; Game Loop代码如下所示:

    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();
        }

    }

GameStateManager是使用update()和draw()方法进行访问的,所以我可以很好地绘制地图,就像旧的原型一样。当我在屏幕上拖动鼠标以便地图可以移动时,问题就出现了;动画变得非常粗糙,在这种程度上我实际上可以看到在所有瓷砖的最终位置之前移动的瓷砖之间的黑色背景。

起初我认为问题在于游戏循环线程和主类的事件监听器之间的并发,因为当JPanel试图绘制地图之前的内容时,可以调用mouseDragged事件;然后我在游戏循环代码上测试了这个:

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

现在原型工作正常。

所以,我的问题是,这个性能是否很重,或者只是Java中的一个不好的做法?另外,是我的&#34;并发&#34;假设对吗?这是我第一次使用Java处理线程,所以我真的不知道我是否以正确的方式处理了这个问题。

obs:这是我制作的游戏循环所在的全班: http://pastebin.com/RMRHYc5X

obs2:如果有人感兴趣,我工作的游戏循环逻辑基于pj644制作的youtube java教程,名为&#34; Java游戏编程&#34;。

obs3:对不起,如果问题变得太大,这是我第一次在这个网站上发帖提问!

1 个答案:

答案 0 :(得分:4)

Swing对于编写游戏来说并不是一项出色的技术,它可以在很多方面缓慢更新并且非常有限。

说过是,调用invokeLater或使用SwingWorker是在游戏线程完成工作时更新屏幕的正确方法。

在你走得太远之前,我真的建议看一下2d或3d java图形和游戏框架。您将能够以这种方式获得更好的结果,并且在设置游戏循环,更新,管理帧速率等方面的大量工作将为您完成。