原始问题

我目前正在开发一个显示地图的简单应用程序,稍后将为单元实现寻路逻辑。到目前为止,我已经实现了地图和视图,并且一切正常,直到实现了游戏循环。

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

编辑:游戏循环继续执行正常,而其他所有东西都冻结了。

这是涉及的两个功能:

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和update尚未更改。

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


更新程序是一个ActionListener,我已将其作为私有变量添加到该类中。

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


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

最佳答案

您没有告诉我们您可能使用的GUI库是什么,但是假设它可能是Swing,就好像您在Swing事件线程上运行了一些长时间运行的代码,该主线程负责执行所有Swing图形并为与用户互动。如果是这样,那么代码将阻止Swing重绘GUI,从而冻结您的应用程序。

我的建议是:


不要这样不要在主事件线程上运行任何长时间运行的代码。
而是考虑使用Swing Timer进行“游戏循环”。
或者,如果必须使用while循环和Thread sleep,请在事件线程之外执行此操作,但是请确保在事件线程上完成所有使Swing对象状态发生变化的Swing调用。
有关Swing线程的更多信息,请阅读Concurrency in Swing

10-04 23:42
查看更多