2016-09-28 112 views
0

我们应该如何在Java中设置固定时间步?我认为有2种方法:如何在Java中设置固定时间步

  1. 同步游戏循环使用while
  2. 使用Thread的异步游戏循环。

最重要的事情是性能准确性。那么最好的方法是什么?

这是同步的游戏循环:

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

这asynchronised游戏循环:

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的画布用于渲染。

你喜欢什么方式?为什么?有没有更好的方法?

+0

如果你想精确,你需要这两者之间的前一种选择。如果没有异常,Thread.sleep会在线程未运行时设置一个*最小值*。调度可能仍会延迟一段任意时间。 –

+0

@DiegoMartinoia是的,但画布呈现在60FPS,我可以设置线程以120Hz完成其工作。 –

+1

计时器似乎最好。如果updateWorld花费太长时间,它应该能够“丢帧”。 –

回答

4

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

这个例子执行Runnable周期性:

ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(); 
executor.scheduleAtFixedRate(myRunnable, initialDelay, period, TimeUnit.MILLISECONDS); 

在你的第一个例子,你的线程在检查巨大的倍量,如果elapsedTime >= timeStep是真实的。它会一直执行检查,直到它是真实的,而不是一次又一次地检查这个检查,直到它终于成真,线程可能正在等待,处理器可能被用于其他事情。

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

相关问题