在游戏循环中使用 sleep() 会使增量时间不稳定
Using sleep() in game loop makes delta time unstable
我正在用 sfml 编写游戏循环。当我不让它休眠时,每次循环迭代经过的时间约为 1 毫秒。但是当我添加 sleep(sleepTime) 突然 dt 很高。我在循环开始时重新启动 dt,但它似乎增加了最后一个睡眠时间。是什么原因造成的?
sf::Clock clock;
float dt;
sf::Time sleepTime = sf::milliseconds(0);
while(m_Window.isOpen())
{
sf::Time elapsed = clock.restart();
dt = elapsed.asMilliseconds();
cout << "Elapsed: " << dt;
sf::Event event;
while(m_Window.pollEvent(event))
{
switch(event.type)
{
case sf::Event::Closed:
m_Window.close();
break;
}
}
sleepTime = sf::milliseconds(16 - dt);
float time = sleepTime.asMilliseconds();
cout << "\tSleep time: " << time << endl;
if(sleepTime >= sf::Time::Zero)
{
sf::sleep(sleepTime);
}
else
{
cout << "Shit." << endl;
}
您尝试做的事情——将游戏限制在一个特定的帧率——已经内置到 SFML 中。只需将您预期的帧率作为参数调用 sf::Window::setFrameRateLimit()
即可。也可以使用垂直同步(通过使用 sf::Window::setVerticalSyncEnabled()
)来限制 frames/updates 的数量,尽管这通常被认为是一个坏主意,因为如果目标机器无法渲染,游戏也会变慢以所需的帧率(或在 120 或 140Hz 下为高端屏幕加速 运行)。
但是,您通常希望将游戏更新与帧速率断开连接,这样游戏就不会变慢,即使当前机器无法足够快地更新屏幕也是如此。
使用 SFML 的基本方法通常如下所示(这是记忆中的,因此可能包含错误或拼写错误):
sf::Clock updateTimer; // Clock to monitor the time passed
sf::Time passedTime; // Accumulated game time
const sf::Time frameTime(sf::milliseconds(10)); // intended time per frame; here: 10ms
while (window.isOpen()) {
sf::Event event;
while (window.pollEvent(event)) {
// Event handling
}
// First add the time passed
passedTime += updateClock.restart();
unsigned int numUpdates = 0; // Count the updates done
// As long as enough time passed, do an update
// Up to a specific maximum to avoid problems, e.g.
// the main thread was blocked or can't catch up
while (passedTime >= frameTime) {
if (numUpdates++ < 10) {
// Do your game update here
}
// Subtract the time we've "handled"
passedTime -= frameTime;
}
window.clear();
// Draw your game here
window.display();
}
numUpdates
的用法一开始可能不太清楚,但请想象一下机器勉强能够 运行 所需的每秒 100 次更新的情况。如果你落后 20 次更新(一些小问题或其他),机器将永远无法再次正确地赶上,导致严重的卡顿或游戏变得无响应。
我正在用 sfml 编写游戏循环。当我不让它休眠时,每次循环迭代经过的时间约为 1 毫秒。但是当我添加 sleep(sleepTime) 突然 dt 很高。我在循环开始时重新启动 dt,但它似乎增加了最后一个睡眠时间。是什么原因造成的?
sf::Clock clock;
float dt;
sf::Time sleepTime = sf::milliseconds(0);
while(m_Window.isOpen())
{
sf::Time elapsed = clock.restart();
dt = elapsed.asMilliseconds();
cout << "Elapsed: " << dt;
sf::Event event;
while(m_Window.pollEvent(event))
{
switch(event.type)
{
case sf::Event::Closed:
m_Window.close();
break;
}
}
sleepTime = sf::milliseconds(16 - dt);
float time = sleepTime.asMilliseconds();
cout << "\tSleep time: " << time << endl;
if(sleepTime >= sf::Time::Zero)
{
sf::sleep(sleepTime);
}
else
{
cout << "Shit." << endl;
}
您尝试做的事情——将游戏限制在一个特定的帧率——已经内置到 SFML 中。只需将您预期的帧率作为参数调用 sf::Window::setFrameRateLimit()
即可。也可以使用垂直同步(通过使用 sf::Window::setVerticalSyncEnabled()
)来限制 frames/updates 的数量,尽管这通常被认为是一个坏主意,因为如果目标机器无法渲染,游戏也会变慢以所需的帧率(或在 120 或 140Hz 下为高端屏幕加速 运行)。
但是,您通常希望将游戏更新与帧速率断开连接,这样游戏就不会变慢,即使当前机器无法足够快地更新屏幕也是如此。
使用 SFML 的基本方法通常如下所示(这是记忆中的,因此可能包含错误或拼写错误):
sf::Clock updateTimer; // Clock to monitor the time passed
sf::Time passedTime; // Accumulated game time
const sf::Time frameTime(sf::milliseconds(10)); // intended time per frame; here: 10ms
while (window.isOpen()) {
sf::Event event;
while (window.pollEvent(event)) {
// Event handling
}
// First add the time passed
passedTime += updateClock.restart();
unsigned int numUpdates = 0; // Count the updates done
// As long as enough time passed, do an update
// Up to a specific maximum to avoid problems, e.g.
// the main thread was blocked or can't catch up
while (passedTime >= frameTime) {
if (numUpdates++ < 10) {
// Do your game update here
}
// Subtract the time we've "handled"
passedTime -= frameTime;
}
window.clear();
// Draw your game here
window.display();
}
numUpdates
的用法一开始可能不太清楚,但请想象一下机器勉强能够 运行 所需的每秒 100 次更新的情况。如果你落后 20 次更新(一些小问题或其他),机器将永远无法再次正确地赶上,导致严重的卡顿或游戏变得无响应。