我有一个简短的问题。我正在学习SFML,并且通过使用它制作了一些应用程序。有一天,我学习了有关在编写游戏代码时使用固定时间步长的知识,如果它行得通的话,那会很棒。但。即使我正在做一个简单的项目,例如正方形从窗口的左侧移动到右侧-还是很滞后!可能是这个问题的原因?这是我的代码:
#include <SFML/Graphics.hpp>
int main()
{
sf::RenderWindow window(sf::VideoMode(800, 600), "Window");
window.setVerticalSyncEnabled(true);
sf::Event event;
sf::Clock clock;
sf::Time accumulator = sf::Time::Zero;
const sf::Time timePerFrame = sf::seconds(1.f / 60.f);
sf::RectangleShape square;
square.setSize(sf::Vector2f(32, 32));
square.setOrigin(16, 16);
square.setPosition(400, 300);
square.setFillColor(sf::Color::Red);
int direction = 1;
int speed = 300;
while(window.isOpen())
{
while(window.pollEvent(event))
{
if(event.type == sf::Event::Closed)
{
window.close();
}
}
while(accumulator >= timePerFrame)
{
if(square.getPosition().x <= 16 || square.getPosition().x >= 784) direction *= (-1);
square.move(sf::Vector2f(speed * direction * timePerFrame.asSeconds(), 0));
accumulator -= timePerFrame;
}
accumulator += clock.restart();
window.clear(sf::Color::Black);
window.draw(square);
window.display();
}
return 0;
}
如您所见,我了解垂直同步,但是并没有太大帮助。我的固定时间步长循环错了吗?任何帮助表示赞赏!
最佳答案
您是否尝试过不启用垂直同步?垂直同步和您已实现的时间步可能都试图同时控制帧速率而互相干扰。在Windows的SFML tutorial page上,它们指出:
“切勿同时使用setVerticalSyncEnabled
和setFramerateLimit
!它们会严重混合并使情况更糟。”
正如您从SFML的源代码中看到的那样:
void Window::setFramerateLimit(unsigned int limit)
{
if (limit > 0)
m_frameTimeLimit = seconds(1.f / limit);
else
m_frameTimeLimit = Time::Zero;
}
void Window::display()
{
// Display the backbuffer on screen
if (setActive())
m_context->display();
// Limit the framerate if needed
if (m_frameTimeLimit != Time::Zero)
{
sleep(m_frameTimeLimit - m_clock.getElapsedTime());
m_clock.restart();
}
}
SFML的
setFramerateLimit
函数的实现与您的时间步基本相同,因此,我认为这里的情况不会有任何不同。在我的机器上测试您的代码后,我确实看到了方形上的一点滞后,但是,禁用垂直同步解决了该问题。
编辑:事实证明,这个问题比我原先想的要复杂(而且如果出现问题,我也忽略了对vsync的明显需求)。经过数天的研究和弄乱了代码,我了解到一些可以解决此问题的事情:
glFinish()
之后调用window.display()
即使启用了vsync,除第一个以外的所有组件都将修复它。这里的主要问题似乎是vsync在窗口模式下无法正常工作,显然这是一个限制,因为该程序必须与不必启用vsync的其他程序共享屏幕空间。
所以我的建议:
glFinish()
调用之后都使用display()
,尽管这样做有一定的代价,但它会暂停CPU并将其与GPU同步,并监视它何时可以异步且不间断地进行处理,但是如果您的程序不是特别占用CPU的,则这应该不是什么大问题。在SFML中,您可以包括“SFML / OpenGL.hpp”以访问此功能。虽然如果您使用的是Windows(我相信是Vista和7,我不知道Windows 8或10是如何处理的),那么在使用Aero主题时,vsync显然会自动启用,因此您可能一开始就不会哭。您使用什么操作系统? 一些进一步的阅读:
启用vsync)
关于c++ - SFML +固定时间步长=滞后?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/39734378/