我正在编写一个相当简单的 2D 多人网络游戏。现在,我发现自己几乎不可能创建一个稳定的循环。稳定是指这样一种循环,其中完成了某些计算并且在严格的时间段内重复(比如说,每 25 毫秒,这就是我现在正在争取的)。到目前为止,我还没有遇到很多严重的障碍,除了这个。
在这个游戏中,服务器和客户端应用程序中都有多个线程正在运行,分配给各种任务。让我们以我的服务器应用程序中的引擎线程为例。在这个线程中,我尝试使用 Thread.sleep 创建游戏循环,尝试考虑游戏计算所花费的时间。这是我的循环,放在 run() 方法中。Tick() 函数是循环的有效负载。它只包含对其他方法进行持续游戏更新的有序调用。
long engFPS = 40;
long frameDur = 1000 / engFPS;
long lastFrameTime;
long nextFrame;
<...>
while(true)
{
lastFrameTime = System.currentTimeMillis();
nextFrame = lastFrameTime + frameDur;
Tick();
if(nextFrame - System.currentTimeMillis() > 0)
{
try
{
Thread.sleep(nextFrame - System.currentTimeMillis());
}
catch(Exception e)
{
System.err.println("TSEngine :: run :: " + e);
}
}
}
主要问题是 Thread.sleep 只是喜欢背叛你对它会睡多少的期望。它可以很容易地让线程休息更长或更短的时间,尤其是在一些装有 Windows XP 的机器上(我自己测试过,与 Win7 和其他操作系统相比,WinXP 给出了非常糟糕的结果)。我在互联网上闲逛了很多,结果令人失望。这似乎是我们正在运行的操作系统的线程调度程序及其所谓的粒度的错误。据我了解,该调度程序在一定时间内不断检查系统中每个线程的需求,特别是将它们从睡眠中唤醒/唤醒。当重新检查时间很短时,比如 1ms,事情可能看起来很顺利。虽然,据说 WinXP 的粒度高达 10 或 15 毫秒。我还读到,不仅是 Java 程序员,但是那些使用其他语言的人也面临这个问题。知道了这一点,似乎几乎不可能做出一个稳定、坚固、可靠的游戏引擎。然而,它们无处不在。我非常想知道通过哪种方式可以解决或规避这个问题。有经验的人可以给我一个提示吗?