游戏循环完全冻结了我的程序

时间:2014-06-21 14:09:50

标签: java swing freeze thread-sleep game-loop

原始问题

我目前正在开发一个显示地图的简单应用程序,稍后将为单位实现路径寻找逻辑。到目前为止,我已经实现了地图和视图,一切运行得很好,直到我实现了游戏循环。

启用游戏循环后,程序就会冻结。即使游戏循环执行得很好,我也无法关闭窗口并且没有显示地图。我过去曾两次使用过这个游戏循环,直到现在才出现任何问题。

编辑:游戏循环继续执行得很好,而其他一切都冻结。

以下是涉及的两个功能:

public GameController() {
    paused = true;

    frame = new GameFrame(this);

    map = new Map(500, 500);
    mvm = new MapViewModel(map.getMap(), map.getWidth(), map.getHeight());

    //TODO: gameLoop() currently breaks the game.

    gameLoop();
}

public void gameLoop() {
    double tickTime, lastTick;

    for (;;) {
        tickTime = System.nanoTime();
        lastTick = tickTime;

        //Repaints the frame
        update();

        while (tickTime - lastTick < NANOSECONDS_PER_UPDATE) {
            try {
                Thread.sleep(1);
            } catch (InterruptedException ignored) {}

            tickTime = System.nanoTime();
        }
    }
}

edit2:我正在使用Swing。实际绘画发生在我的GamePanel(JPanel)的paintComponent方法中:

@Override
public void paintComponent(Graphics g) {
    Graphics2D g2 = (Graphics2D) g;

    //Paints the map
    painter.paintMap(g2, controller.getMvm());
}

显然,如果您有任何进一步的问题,请随时提出。提前谢谢。

解决方案

这是我现在使用的代码,GameController和更新尚未更改。

public void gameLoop() {
    timer = new Timer(MILLISECONDS_PER_UPDATE, updater);
    timer.start();
}

updater是一个ActionListener,我已将其作为私有变量添加到类中。

private ActionListener updater = new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
        System.out.println("test2");
        update();
    }
};

您可以在本地添加更新程序,但我更喜欢这种方式。

1 个答案:

答案 0 :(得分:4)

您没有告诉我们您可能正在使用的GUI库,但假设它可能是Swing,看起来您正在Swing事件线程上运行一些长时间运行的代码,主线程负责执行所有Swing图形以及与用户交互。如果是这样,那么代码将阻止Swing重新绘制GUI,冻结您的应用程序。

我的建议是:

  • 不要这样做。不要在主事件线程上运行任何长时间运行的代码。
  • 相反,请考虑使用Swing Timer来进行#34;游戏循环&#34;。
  • 或者如果你必须使用你的while循环和线程休眠,那么从事件线程开始,然后确保所有改变Swing对象状态的Swing调用都在 on 事件中完成线程。
  • 有关Swing线程的更多信息,请阅读Concurrency in Swing