如何在Java中制作固定时间步长
我们应该如何在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
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和计时器之间的区别,有一个问题: