Java 主游戏循环

2022-09-02 12:46:59

我正在编写一个游戏循环,我在这里的示例中找到代码。我还研究了执行游戏循环的其他方法,例如本文。我无法让这些工作中的任何一个。所以我保留了第一个链接中的那个。

我想知道:

  • 我编写游戏循环的方式是执行此操作的好方法吗?
    • 有什么建议吗?
  • 我应该在游戏循环中使用吗?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){
        }
    }

答案 1

最终你会想搬到像LWJGL这样的东西,但让我强调一下,继续做你现在在这里做的事情。它会教你基础知识。

在你的循环中做得很好。看起来不错,让我提供一些提示:

  • 重绘不会立即呈现屏幕。它告诉重绘管理器在准备就绪时进行渲染。请立即使用无效的 paint。 将阻止执行,直到重新绘制组件,以便您可以测量渲染时间。paintImmediately

  • Thread.sleep通常有几毫秒的漂移。你应该用它来防止你的循环使用太多的CPU,但一定要明白,如果你睡了10毫秒,你可能会睡5毫秒,或者你可能会睡20分钟。

  • 最后:

    double delta = updateLength / ((double)OPTIMAL_TIME);
    

    如果小于 OPTIMAL_TIME,请不要调用 update。换句话说,如果 delta 小于 1,则不要更新。本教程解释了为什么比我更好。updateLength


答案 2

总的来说,这是一个很好的循环,但是我发现在经验中发现的是最好的循环中,有一些缺失的方面。

您最终将希望迁移到 LWJGL 或其他一些 Java 游戏 API,但现在,请了解游戏循环如何工作的基础知识,以及最适合您需求的方法。

  • 首先,回答你的一个问题,不。你会做得更好 远离

    Thread.sleep()

    这可能会偏离您将其设置为睡眠的真实时间量。
    例如,如果您将其设置为睡眠10毫秒,它可以使程序休眠5到20毫秒。

  • 我立即看到的第二个问题是,你没有任何方法可以停止自定义stop()方法的游戏循环。尝试

    布尔运行 = 真;
    同时 (运行) {
    // 你的代码在这里 //
    }

  • 第三,您可能需要考虑更改使用增量变量的方式。下面代码中的方式可能是更好的使用和构造。

    这是我在程序中使用的游戏循环的一个示例:

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

推荐