如何在Java中制作固定时间步长

如何在Java中制作固定时间步长,java,game-loop,Java,Game Loop,我们应该如何在Java中创建固定时间步长?我认为有两种方法: 使用while同步游戏循环 使用线程的异步游戏循环 最重要的是性能和准确性。那最好的办法是什么呢 这是同步游戏循环: double timeStep = world.getSettings().getStepFrequency(); long lastTime = System.nanoTime(); while (true) { long currentTime = System.nanoT

我们应该如何在Java中创建固定时间步长?我认为有两种方法:

  • 使用
    while
    同步游戏循环
  • 使用
    线程的异步游戏循环
  • 最重要的是性能和准确性。那最好的办法是什么呢

    这是同步游戏循环:

        double timeStep = world.getSettings().getStepFrequency();
        long lastTime = System.nanoTime();
    
        while (true) {
            long currentTime = System.nanoTime();
            double elapsedTime = (currentTime - lastTime) / 1000000000.0;
    
            if (elapsedTime >= timeStep) {
                lastTime = currentTime;
                world.update(elapsedTime);
            }
        }
    
        double timeStep = world.getSettings().getStepFrequency();
        long lastTime = System.nanoTime();
    
        Thread loop = new Thread() {
            public void run() {
                while (true) {
                    long currentTime = System.nanoTime();
                    double elapsedTime = (currentTime - lastTime) / 1000000000.0;
                    lastTime = currentTime;
    
                    world.update(elapsedTime);
    
                    try {
                        Thread.sleep((long) Math.floor(timeStep * 1000));
                    } catch (InterruptedException e) {}
                }
            }
        };
        loop.start();
    
    这是异步的游戏循环:

        double timeStep = world.getSettings().getStepFrequency();
        long lastTime = System.nanoTime();
    
        while (true) {
            long currentTime = System.nanoTime();
            double elapsedTime = (currentTime - lastTime) / 1000000000.0;
    
            if (elapsedTime >= timeStep) {
                lastTime = currentTime;
                world.update(elapsedTime);
            }
        }
    
        double timeStep = world.getSettings().getStepFrequency();
        long lastTime = System.nanoTime();
    
        Thread loop = new Thread() {
            public void run() {
                while (true) {
                    long currentTime = System.nanoTime();
                    double elapsedTime = (currentTime - lastTime) / 1000000000.0;
                    lastTime = currentTime;
    
                    world.update(elapsedTime);
    
                    try {
                        Thread.sleep((long) Math.floor(timeStep * 1000));
                    } catch (InterruptedException e) {}
                }
            }
        };
        loop.start();
    
    同步游戏循环使用大量CPU(我认为是1核?对我来说大约是25%)

    异步游戏循环的CPU使用率几乎为0%

    注意:我想做的游戏是基于
    WebSocket
    的游戏。服务器用于物理,HTML5的画布用于渲染


    你喜欢哪种方式?为什么?有更好的方法吗?

    Java API中有一些类可以定期执行任务。最好不要尝试重新发明轮子并使用JavaAPI。A似乎是你需要的

    本例定期执行
    Runnable

    ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
    executor.scheduleAtFixedRate(myRunnable, initialDelay, period, TimeUnit.MILLISECONDS);
    
    在第一个示例中,如果
    elapsedTime>=timeStep
    为真,线程将检查大量的时间。它会一直执行检查直到它为真,而不是一次又一次地执行检查直到它最终为真,线程可能会等待,处理器可能会被用于其他事情


    第二个选项比第一个好,因为线程等待下一次执行的时间段

    Java API中有一些类可以定期执行任务。最好不要尝试重新发明轮子并使用JavaAPI。A似乎是你需要的

    本例定期执行
    Runnable

    ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
    executor.scheduleAtFixedRate(myRunnable, initialDelay, period, TimeUnit.MILLISECONDS);
    
    在第一个示例中,如果
    elapsedTime>=timeStep
    为真,线程将检查大量的时间。它会一直执行检查直到它为真,而不是一次又一次地执行检查直到它最终为真,线程可能会等待,处理器可能会被用于其他事情


    第二个选项比第一个好,因为线程等待下一次执行的时间段

    如果你想要精确,你需要在这两者之间选择前者。如果没有异常,Thread.sleep将设置线程未运行的最小数量。调度可能仍然会延迟任意时间。@DiegoMartinoia是的,但画布渲染速度为60FPS,我可以将线程设置为120Hz。计时器似乎是最好的。如果updateWorld花费的时间太长,它应该能够“删除帧”。@JoopEggen请回答这个问题,如果可以:)为什么选择计时器、加号、减号、线程之间的区别等等。有一个问题是关于ExecutorService和计时器之间的区别:如果你想要精度,你需要在这两者之间选择前者。如果没有异常,Thread.sleep将设置线程未运行的最小数量。调度可能仍然会延迟任意时间。@DiegoMartinoia是的,但画布渲染速度为60FPS,我可以将线程设置为120Hz。计时器似乎是最好的。如果updateWorld花费的时间太长,它应该能够“删除帧”。@JoopEggen请回答问题,如果可以:)为什么选择计时器、加号、减号、线程之间的区别等。关于ExecutorService和计时器之间的区别,有一个问题: