原始问题
我目前正在开发一个显示地图的简单应用程序,稍后将为单元实现寻路逻辑。到目前为止,我已经实现了地图和视图,并且一切正常,直到实现了游戏循环。
启用游戏循环后,程序将冻结。即使游戏循环执行得很好,我也无法再关闭窗口,也不会显示地图。我过去曾两次使用此游戏循环,直到现在再也没有任何问题。
编辑:游戏循环继续执行正常,而其他所有东西都冻结了。
这是涉及的两个功能:
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。