【问题标题】:SFML extremly slow/irregular framerateSFML 极慢/不规则帧率
【发布时间】:2015-11-24 22:22:18
【问题描述】:

我最近一直在寻找 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;
}

老实说,我什至不知道从哪里开始寻找解决方案。 我想这可能与驱动程序有关,我明天将在另一台计算机上测试它。 对此的任何建议将不胜感激。

编辑以回应艾克: 我从 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++ 编译了上面的代码。 我无法想象这是一个优化问题,因为游戏循环似乎每秒可能经历两打迭代(最多)。我不能肯定地说,但我相信这个数字应该是数千。

另一个编辑:好的,所以我再次使用 repo-libraries 在 Ubuntu-VM 中编译了相同的代码。圆圈现在移动得相当快,这比我猜的好(并且还暗示了 debian 的一些问题,可能与驱动程序相关?)。在另一台运行 arch 并使用 sfml 2.3.2 的计算机上(公认比我的笔记本电脑快),程序运行速度轻松十倍

【问题讨论】:

  • 你最终完全解决了这个问题吗?我没有您遇到的跳过问题,但对我来说,移动似乎缓慢而笨重。

标签: c++ sfml


【解决方案1】:

有几件事可以尝试:

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

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

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

我怀疑您看到的是事件队列被自动重复的关键事件发送的结果。然后,这将切入调用 updaterender 等函数的频率并破坏平滑帧速率。

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

【讨论】:

  • 禁用重复键解决了部分问题,谢谢! (我有点困惑,这本书甚至没有提到这一点,也许我以某种方式忽略了它)。尽管如此,进行两次更正后,圆圈移动得相当慢(尽管也更规律),据我了解,这并不完全正确,因为没有限制帧速率或圆圈速度的机制。
  • 很高兴它有点帮助。现在看来我们只有一个普遍的速度问题。就像一个健全性检查(希望这不是一个冒犯性的问题),代码和库都是在优化的基础上构建的?
  • 哎呀——“每秒两次迭代”。我必须承认,我从未使用过 SFML——我的回答只是基于对事件处理的一般理解以及它在游戏循环中的应用方式。但要弄清楚为什么迭代次数如此之少,可能需要对 API 有更具体了解的人。
  • 但是,如果你只从一个在屏幕上画一个圆圈的简单程序中得到这么多,那肯定是大错特错了。
  • 我现在会尝试安装当前的稳定版本(2.3.2),我想我应该马上安装,但我认为 repo-version 可以很好地进行一些快速测试跨度>
【解决方案2】:

从我的相关问题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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-08-20
    • 1970-01-01
    • 1970-01-01
    • 2018-09-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多