0
\$\begingroup\$

Similar to this question https://stackoverflow.com/questions/33904998/sfml-extremly-slow-irregular-framerate, I have created a small program to experiment with SFML

I have a very simple SFML test application on ubuntu 20.04 using SFML 2.5.1. There are three circles. One under user control and one bouncing left to right.

Problems:

  • The one moving left to right is not very fast.
  • Even so the one under user control cannot keep up with it.
  • I am using a delta of 1 (pixel per frame?). If I increase this motion is jumpy rather than smooth.

Put simply it feels clunky. So I am assuming I've made a noob error of some kind. However, this seems to be the same basic SFML game loop commonly used. How can I make this fast and slick feeling instead?

#include <SFML/Graphics.hpp>

int main()
{
    sf::RenderWindow window(sf::VideoMode(200, 200), "SFML works!");
    const float FPS = 120.0f; //The desired FPS. (The number of updates each second).
    bool redraw = true;      //Do I redraw everything on the screen?
    window.setFramerateLimit(FPS);
    sf::CircleShape shape2(100.f);
    sf::CircleShape shape(10.f);
    sf::Clock clock;
    shape2.setFillColor(sf::Color::Green);
    shape.setFillColor(sf::Color::Red);

    sf::CircleShape alien(10.f);
    alien.setFillColor(sf::Color::Yellow);
    auto alienSpeed = 1.f;
   
    while (window.isOpen())
    {
        sf::Event event;
        float xDelta = 0;
        float yDelta = 0;
        bool moved = false;
        if (window.pollEvent(event))
        {
           if (event.type == sf::Event::Closed)
           {
              window.close();
           }
           if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
            {
               xDelta -= 1.f;
               moved = true;
            }
            else if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
            {
               xDelta += 1.f;
               moved = true;
            }
            if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up))
            {
               yDelta -= 1.f;
               moved = true;
            }
            else if (sf::Keyboard::isKeyPressed(sf::Keyboard::Down))
            {
               yDelta += 1.f;
               moved = true;
            }
        }

        if (xDelta !=0 || yDelta != 0)
        {
           shape.move(xDelta,yDelta);
        }

        alien.move(alienSpeed, 0.f);
        if (alien.getPosition().x >= 190)
        {
           alienSpeed = -1.f;
        }
        else if (alien.getPosition().x <= 0)
        {
           alienSpeed = 1.f;
        }

        if(redraw)
        {
           window.clear();
           window.draw(shape2);
           window.draw(shape);
           window.draw(alien);
           window.display();
        }
    }

    return 0;
}

Note: cross posted to https://en.sfml-dev.org/forums/index.php?topic=27617.0

\$\endgroup\$
1
  • 1
    \$\begingroup\$ It looks like your game loop is missing the notion of a time step. Your code assumes that exactly one pixel worth of time has passed in each iteration. But if you time the loop, I bet that's not the case. You probably have some iterations that happen closer back-to-back than others. At higher velocities, that can create an effect called "judder" — where our eye, assuming the object is moving at a constant-ish velocity, expects the object to be in one place by now, but it actually ends up a few pixels ahead or behind because of this time variation, making it look like it's jumping or vibrating. \$\endgroup\$ Commented Sep 19, 2020 at 13:49

1 Answer 1

1
\$\begingroup\$

Answered in the SFML forum by eXpl0it3r:

You should not be mixing events and real-time inputs, see the dedicated tutorials.

Events: https://www.sfml-dev.org/tutorials/2.5/window-events.php Real-time input: https://www.sfml-dev.org/tutorials/2.5/window-inputs.php

It is (as I thought) a noob error. sf::Keyboard::isKeyPressed() is not an event and does not belong inside the event processing loop. With isKeyPressed() outside that loop its much better. It should be:

    if (window.pollEvent(event))
    {
       if (event.type == sf::Event::Closed)
       {
          window.close();
       }
    }

    if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
    {
           xDelta -= 1;
    }
\$\endgroup\$

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.