0

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 &gt;= 190)
    {
       alienSpeed = -1.f;
    }
    else if (alien.getPosition().x &lt;= 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

Bruce Adams
  • 111
  • 2
  • 1
    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. – DMGregory Sep 19 '20 at 13:49

1 Answers1

1

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;
}

Bruce Adams
  • 111
  • 2