在 Java 游戏循环中使用“SwingUtilities.invokeLater()”是一种不好的做法吗?

use*_*123 4 java swing game-loop

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

在实际原型版本之前,我构建了一个本身没有“游戏循环”的小型 Java 应用程序;唯一更新 tile-map 位置的是鼠标拖动的事件侦听器,它在移动更新后调用 repaint() 方法。它工作正常,我可以选择瓷砖并毫无问题地移动地图。

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

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

    }
Run Code Online (Sandbox Code Playgroud)

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

起初我以为问题出在游戏循环线程和主类的事件侦听器之间的并发性,因为可以在 JPanel 尝试绘制刚才绘制的地图时调用 mouseDragged 事件;然后我在我的游戏循环代码上测试了这个:

        SwingUtilities.invokeLater(new Runnable(){
            public void run(){
                draw();
                drawToScreen();
            }
        });
        //draw();
        //drawToScreen();
Run Code Online (Sandbox Code Playgroud)

现在原型工作得很好。

所以,我的问题是,这种性能是沉重的,还是在 Java 中只是一种不好的做法?另外,我的“并发”假设是否正确?这是我第一次在 Java 中处理线程,所以我真的不知道我是否以正确的方式处理了这个问题。

obs:这是我制作的游戏循环所在的整个课程:http : //pastebin.com/RMRHYc5X

obs2:如果有人感兴趣,我使用的游戏循环逻辑是基于 pj644 制作的名为“Java 中的 2D 游戏编程”的 youtube java 教程。

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

Tim*_*m B 5

Swing 并不是真正的编写游戏的好技术,它更新缓慢,而且在很多方面都非常有限。

话虽如此,当您的游戏线程完成其工作时,调用invokeLater或使用 aSwingWorker将是更新屏幕的正确方法。

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