SFML的帧速率极慢/不规则

SFML extremly slow/irregular framerate

本文关键字:不规则 帧速率 SFML      更新时间:2023-10-16

我最近一直在寻找C++游戏开发框架,并决定尝试一下SFML。我已经实现了《SFML游戏开发》一书中的一个早期例子,看看事情是否正常。遗憾的是,他们没有。

当按下其中一个"wasd"键时,该代码应该使圆形对象快速移动。事实上,圆圈开始缓慢移动大约十个像素的距离,然后停止,如果我进一步按下相应的键,圆圈就会在任何时候跳跃几个像素。

//the header game.h
class Game
{
public:
    Game();
    void run();
private:
    void processEvents();
    void handlePlayerInput(sf::Keyboard::Key, bool);
    void update();
    void render();
    sf::RenderWindow mWindow;
    sf::CircleShape mPlayer;
    bool mIsMovingUp;
    bool mIsMovingDown;
    bool mIsMovingLeft;
    bool mIsMovingRight;
};
//the implementation
#include<SFML/Graphics.hpp>
#include "game.h"
Game::Game()
: mWindow(sf::VideoMode(640, 480), "SFML Application")
, mIsMovingUp(false), mIsMovingDown(false), mIsMovingLeft(false), mIsMovingRight(false)
, mPlayer()
{
    mPlayer.setRadius(40.f);
    mPlayer.setPosition(100.f, 100.f);
    mPlayer.setFillColor(sf::Color::Cyan);
}
void Game::run()
{
    while (mWindow.isOpen())
    {
        processEvents();
        update();
        render();
    }
}
void Game::render() 
{
    mWindow.clear();
    mWindow.draw(mPlayer);
    mWindow.display();
}
void Game::processEvents()
{
    sf::Event event;
    while (mWindow.pollEvent(event))
    {
        switch (event.type)
        {
            case sf::Event::KeyPressed:
                handlePlayerInput(event.key.code, true);
                break;
            case sf::Event::KeyReleased:
                handlePlayerInput(event.key.code, false);
                break;
            case sf::Event::Closed:
                mWindow.close();
                break;
        }
    }
}
void Game::handlePlayerInput(sf::Keyboard::Key key, bool isPressed)
{
    if (key == sf::Keyboard::W)
            mIsMovingUp = isPressed;
    else if (key == sf::Keyboard::S)
            mIsMovingDown = isPressed;
    else if (key == sf::Keyboard::A)
            mIsMovingLeft = isPressed;
    else if (key == sf::Keyboard::D)
            mIsMovingRight = isPressed;
}
void Game::update()
{
    sf::Vector2f movement(0.f, 0.f);
    if (mIsMovingUp)
        movement.y -= 1.0f;    
    if (mIsMovingDown)
        movement.y += 1.0f;
    if (mIsMovingLeft)
        movement.x -= 1.0f;
    if (mIsMovingRight)
        movement.x += 1.0f;
    mPlayer.move(movement);
}
//main file
#include <SFML/Graphics.hpp>
#include "game.h"
int main()
{
    Game game;
    game.run();
    return 0;
}

老实说,我甚至不知道从哪里开始寻找解决方案。我想这可能与驱动程序有关,我明天会在另一台电脑上测试它。如有任何建议,我们将不胜感激。

编辑以回应Ike:我从Debian存储库中获得了SFML库,运行

`dpkg -l | grep sfml`

退货:

ii  libsfml-audio2:amd64                 2.1+dfsg2-1+b2                  
ii  libsfml-dev:amd64                    2.1+dfsg2-1+b2                       
ii  libsfml-graphics2:amd64              2.1+dfsg2-1+b2                       
ii  libsfml-network2:amd64               2.1+dfsg2-1+b2                       
ii  libsfml-system2:amd64                2.1+dfsg2-1+b2                       
ii  libsfml-window2:amd64                2.1+dfsg2-1+b2    

我使用-O2标志用g++编译了上面的代码。我无法想象这是一个优化问题,因为游戏循环似乎每秒(最多)要经历20多次迭代。我不能肯定地说,但我相信这个数字应该是数千。

另一个编辑:好吧,所以我再次使用repo库在Ubuntu虚拟机中编译了相同的代码。圆圈现在移动得相当快,我想这总比什么都没有好(也暗示了debian的一些问题,可能与司机有关?)。在另一台运行arch并使用sfml 2.3.2的计算机上(公认比我的笔记本电脑快),该程序运行速度是的十倍

要尝试的几件事:

A) 设置mWindow.setKeyRepeatEnabled(false)。这将禁用自动重复。

B) 尝试将Game::processEvents更改为使用if而不是while,如下所示:

void Game::processEvents()
{
    sf::Event event;
    if (mWindow.pollEvent(event))
    {
        ...
    }
}

我怀疑您看到的是事件队列中自动重复关键事件的结果。这将降低调用updaterender等函数的频率,并破坏平滑帧速率。

第一个建议试图消除这种堵塞队列的可能性。第二种方法使更新/刷新在事件处理之间交错进行,而不仅仅是在事件队列变空时执行。

从我的相关问题判断https://gamedev.stackexchange.com/questions/185873/sfml-test-app-feels-slow-clunky/185880#185880问题可能是您使用的是键盘事件,而不是实时键盘输入。即sf::Keyboard::isKeyPressed

请参阅https://www.sfml-dev.org/tutorials/2.5/window-inputs.php