我的 SFML/C++ 程序按预期工作,但如何使移动变慢

My SFML/C++ program is working as expected but how to make movement slow?

本文关键字:何使 移动 工作 SFML C++ 程序 我的      更新时间:2023-10-16

我作为我们的玩家做了一个圆圈并设置了重力,但它的工作速度要快得多,我什至看不到。我认为它必须与 sf::time 或 sf::clock 做一些事情,但是如何做呢?我实际上没有得到这两个,所以任何代码示例和解释将不胜感激。这是我的代码:-

#include <SFML/Graphics.hpp>
int main()
{
    sf::RenderWindow window(sf::VideoMode(800, 600), "SFML works!");
    sf::CircleShape shape(20);
    shape.setFillColor(sf::Color::White);
    shape.setPosition(380, 550);
    shape.setOutlineColor(sf::Color::Green);
    shape.setOutlineThickness(3);
    while (window.isOpen())
    {
        sf::Event event;
        while (window.pollEvent(event))
        {
            if (event.type == sf::Event::Closed)
                window.close();
            if(sf::Keyboard::isKeyPressed(sf::Keyboard::Up))
                {
                    shape.move(0, -100);
                }
                if(event.KeyReleased)
                {
                    if(event.key.code == sf::Keyboard::Up)
                    {
                    int x[] = { 10, 10, 10, 10, 10};
                    for (int y = 0; y <= 4; y++)
                    {
                        shape.move(0, x[y]);
                    }
                    }
                }
        }
        window.clear(sf::Color::Black);
        window.draw(shape);
        window.display();
    }
    return 0;
}
请记住,

您的程序可能每秒运行数百帧,因此当您按下键盘上的向上按钮时,它会移动对象-每帧 100 像素,这绝对不是您想要的。

那么如何解决这个问题呢?你需要包括时间的概念。为此,我们使用时间步长来查看自调用最后一帧以来已经过去了多少时间。

这是一个简短的示例代码,显示了如何构建此时间步(有许多不同的方法,每种方法都有优点和缺点)。

sf::Time timePerFrame = sf::seconds(1.0f / 60.0f); // 60 frames per second
sf::Clock deltaClock;  // This will track how much time has past since the last frame
sf::Time timeSinceLastUpdate = sf::Time::Zero;
while (m_Window.isOpen())
{
    sf::Time deltaTime = deltaClock.restart();  // Restart returns the time since the last restart call
    timeSinceLastUpdate += deltaTime;
    while (timeSinceLastUpdate >= timePerFrame)
    {
        timeSinceLastUpdate -= timePerFrame;
        ProcessInput();
        Update(timePerFrame);  // Notice how I pass the time per frame to the update function
    }
    Render();
}

然后在更新代码中,您只需将要移动的距离乘以传递到更新函数中的对象 timePerFrame(确保使用 sf::Time::asSeconds() )。例如,您的代码如下所示

shape.move(0, -100 * timePerFrame.asSeconds());

如果您正在寻找有关时间步长如何工作的深入解释,我会推荐这篇文章 http://gafferongames.com/game-physics/fix-your-timestep/

正如@Zereo所回应的那样,但有一个简化的版本:与其照顾帧率,不如让 SFML 照顾:

    window.setFramerateLimit(60);

在创建窗口后放置此行,SFML 会将您的帧限制为 60/s。