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