Java主游戏循环
我正在编写游戏循环,我在下面的示例中找到了代码。 我还研究了其他方法来进行游戏循环,例如本文 。 我无法让任何那些工作。 所以我保留了第一个链接中的那个。
我想知道的是:
- 我编写游戏循环的方式是一种很好的方法吗?
- 有什么建议么?
- 我应该使用
Thread.sleep();
在我的游戏循环中?
这是我目前的代码:
public void run(){ long lastLoopTime = System.nanoTime(); final int TARGET_FPS = 60; final long OPTIMAL_TIME = 1000000000 / TARGET_FPS; long lastFpsTime = 0; while(true){ long now = System.nanoTime(); long updateLength = now - lastLoopTime; lastLoopTime = now; double delta = updateLength / ((double)OPTIMAL_TIME); lastFpsTime += updateLength; if(lastFpsTime >= 1000000000){ lastFpsTime = 0; } this.updateGame(delta); this.repaint(); try{ Room.gameTime = (lastLoopTime - System.nanoTime() + OPTIMAL_TIME) / 1000000; System.out.println(Room.gameTime); Thread.sleep(Room.gameTime); }catch(Exception e){ } }
最终你会想要转向像LWJGL这样的东西 ,但让我强调一下,继续做你现在在做的事。 它将教你基本面。
你的循环很好。 看起来不错,让我提供一些指示:
-
重绘不会立即渲染屏幕。 它告诉RepaintManager在准备好时进行渲染。 请改用paintImmediately 。
paintImmediately
将阻止执行,直到重新绘制组件,以便您可以测量渲染时间。 -
Thread.sleep
通常有几毫秒的漂移。 您应该使用它来防止循环使用太多的CPU,但要确保您了解您是否睡眠10毫秒,您可能会睡5毫秒,或者您可能睡20。 -
最后:
double delta = updateLength / ((double)OPTIMAL_TIME);
如果
updateLength
小于OPTIMAL_TIME,请不要调用update。 换句话说,如果delta小于1,则不要更新。 本教程解释了为什么比我更好。
总的来说,这是一个很好的循环,但是我在经验中找到的最好的循环有一些缺失的方面。
你最终会想要转移到LWJGL或其他一些Java游戏API,但是现在,学习游戏循环如何工作的基础知识,以及最适合你需求的东西。
-
首先,回答你的一点,没有。 你会做得更好远离
Thread.sleep()方法
这可能会偏离您将其设置为睡眠的实际时间。
例如,如果将其设置为hibernate10毫秒,它可以使程序hibernate5到20毫秒。 -
我立即看到的第二个问题是你没有办法停止自定义stop()方法的游戏循环。 尝试
boolean running = true;
在跑步的时候) {
//你的代码//
} -
第三,您可能需要考虑更改使用delta变量的方式。 下面的代码中的方式可能是一个更好的使用和构造。
这是我在我的程序中使用的游戏循环的一个例子:
@Override public void run() { long initialTime = System.nanoTime(); final double timeU = 1000000000 / UPS; final double timeF = 1000000000 / FPS; double deltaU = 0, deltaF = 0; int frames = 0, ticks = 0; long timer = System.currentTimeMillis(); while (running) { long currentTime = System.nanoTime(); deltaU += (currentTime - initialTime) / timeU; deltaF += (currentTime - initialTime) / timeF; initialTime = currentTime; if (deltaU >= 1) { getInput(); update(); ticks++; deltaU--; } if (deltaF >= 1) { render(); frames++; deltaF--; } if (System.currentTimeMillis() - timer > 1000) { if (RENDER_TIME) { System.out.println(String.format("UPS: %s, FPS: %s", ticks, frames)); } frames = 0; ticks = 0; timer += 1000; } } }