SFML community forums

Help => General => Topic started by: Jycerian on November 19, 2014, 03:23:47 pm

Title: Jerky gameplay
Post by: Jycerian on November 19, 2014, 03:23:47 pm
Hi guys, made a small sample program. That will eventually become my second game. But I got this weird jerky game-play when moving around etc... also notice some screen-tearing and I dont get what causes this weird phenomenon.

Executable: http://puu.sh/cX70G/9dc21552d5.zip (http://puu.sh/cX70G/9dc21552d5.zip)
Project Files: http://puu.sh/cX7j3/fd2d7c3238.zip (http://puu.sh/cX7j3/fd2d7c3238.zip)

Anyone got any clue's? Is it also jerky on your computer?

const sf::Time Game::kTimePerFrame = sf::seconds(1.f / 60.f);

Game::Game()
    : window_(sf::VideoMode(720, 540), "Prototype"),
      player_("assets/textures/player.png") {
  window_.setVerticalSyncEnabled(true); // Without this there is less stuttering but also takes like 45% cpu
  camera_.AdaptSize(window_); // Simply gets window size, and set view to same size.
  camera_.Attach(player_); // Set view/camera center to player

  if (!background_texture.loadFromFile("assets/textures/background.png"))
    std::cout << "Failed to load background.png" << std::endl;

  background_.setTexture(background_texture);
}

// Logic loop is fixed at 60, render loop unlimited but limited with v-sync.
void Game::Run() {
  sf::Clock clock;
  sf::Time timeSinceLastUpdate = sf::Time::Zero;
  while (window_.isOpen()) {
    timeSinceLastUpdate += clock.restart();
    while (timeSinceLastUpdate > kTimePerFrame) {
      timeSinceLastUpdate -= kTimePerFrame;

      ProcessEvents();
      Update(kTimePerFrame);
    }
    Render();
  }
}

void Game::ProcessEvents() {
  sf::Event event;
  while (window_.pollEvent(event)) {
    if (event.type == sf::Event::Closed)
      window_.close();

    player_.ProcessEvents(event); // Player events like walking...
  }
}

void Game::Update(const sf::Time& dt) {
  player_.Update(dt);
  camera_.Update(dt);
}

void Game::Render() {
  window_.setView(camera_.GetView()); // Get sf::view from camera class.
  window_.clear(sf::Color(15, 15, 15, 255));
  window_.draw(background_);
  window_.draw(player_);
  window_.display();
}
 

The camera class and player class are very simple so I didn't include them. Could the problem be in this code? I also have an old Asus k52n laptop.
Title: Re: Jerky gameplay
Post by: Nexus on November 19, 2014, 03:38:45 pm
Please reproduce it with a minimal complete example (http://en.sfml-dev.org/forums/index.php?topic=5559.msg36368#msg36368) and give details (http://en.sfml-dev.org/forums/index.php?topic=5559.msg36368#msg36368). The reason why I'm saying this because "jerky gameplay" can mean several things and result from various reasons, including bugs in your own code, e.g. bad time handling or too low framerate.

You can use VSync against screen tearing.
Title: Re: Jerky gameplay
Post by: Jesper Juhl on November 19, 2014, 04:02:04 pm
Here (https://github.com/SFML/SFML/wiki/Source%3A-Bouncing-ball) is a small example that should run reasonably smooth and without tearing. Does it?
Title: Re: Jerky gameplay
Post by: Jycerian on November 19, 2014, 04:07:13 pm
Here (https://github.com/SFML/SFML/wiki/Source%3A-Bouncing-ball) is a small example that should run reasonably smooth and without tearing. Does it?

Also pretty jerky on my machine, windows 7. Can you run my executable smoothly?
Title: Re: Jerky gameplay
Post by: Jesper Juhl on November 19, 2014, 05:10:37 pm
Can you run my executable smoothly?
No. I don't have access to a Windows machine.
Title: Re: Jerky gameplay
Post by: Hapax on November 19, 2014, 09:00:01 pm
Here (https://github.com/SFML/SFML/wiki/Source%3A-Bouncing-ball) is a small example that should run reasonably smooth and without tearing. Does it?
Just tried this out. Needs more balls  :P
The ball doesn't collide properly with the window edge. I suggest you change the ball's origin from:
ball.setOrigin(ball_radius / 2, ball_radius / 2);
to
ball.setOrigin(ball.getRadius(), ball.getRadius());
to correctly use the filled circle's radius (ball_radius - 4) to position the origin.

An easy oversight to make  ;)
Title: Re: Jerky gameplay
Post by: Jycerian on November 19, 2014, 09:58:00 pm
Here (https://github.com/SFML/SFML/wiki/Source%3A-Bouncing-ball) is a small example that should run reasonably smooth and without tearing. Does it?
Just tried this out. Needs more balls  :P
The ball doesn't collide properly with the window edge. I suggest you change the ball's origin from:
ball.setOrigin(ball_radius / 2, ball_radius / 2);
to
ball.setOrigin(ball.getRadius(), ball.getRadius());
to correctly use the filled circle's radius (ball_radius - 4) to position the origin.

An easy oversight to make  ;)

Please keep it on-topic ;) that is not my example hihi.
Title: Re: Jerky gameplay
Post by: Hapax on November 20, 2014, 01:24:40 am
Please keep it on-topic
Sure. Post a complete and minimal example and I'll test it  :P
Title: Re: Jerky gameplay
Post by: Jycerian on November 23, 2014, 07:26:37 pm
Also has this weird jerky movement and screen tearing in another game I made but I decided to ignore it. Now I finally want to fix it somehow so I am able to get smooth gameplay in my next game.

I have an Asus k52n laptop running windows 7 64bit.

Cpu: AMD Athlon X2 P320 2,1GHz
Memory: 4 GB
Videocard: AMD Radeon HD 4200

Example:

#include <SFML/Graphics.hpp>

// 1 second / 60
const sf::Time timePerFrame = sf::seconds( 1.f / 60.f );

int main() {
  // Init window
  sf::RenderWindow window( sf::VideoMode( 720, 540 ), "Demo" );
  window.setVerticalSyncEnabled( true );

  // Init variables
  float playerSpeed = 200.f;
  bool isMovingUp = false;
  bool isMovingDown = false;
  bool isMovingLeft = false;
  bool isMovingRight = false;

  // Load images
  sf::Texture background_tex;
  if ( !background_tex.loadFromFile( "background.png" ) ) {
    // Error handling..
  }

  sf::Texture player_tex;
  if ( !player_tex.loadFromFile( "player.png" ) ) {
    // Error handling..
  }

  // Setup sprites
  sf::Sprite background;
  background.setTexture( background_tex );

  sf::Sprite player;
  player.setTexture( player_tex );
  player.setOrigin( player.getLocalBounds().width / 2,
    player.getLocalBounds().height / 2 );

  // Create view and set size equal to window
  sf::View camera;
  camera.setSize( sf::Vector2f(window.getSize()) );

  // Main loop, update at 60. Render at unlimited but locked
  // with v-sync at 60.
  sf::Clock clock;
  sf::Time timeSinceLastUpdate = sf::Time::Zero;
  while ( window.isOpen() ) {
    timeSinceLastUpdate += clock.restart();
    while ( timeSinceLastUpdate > timePerFrame ) {
      timeSinceLastUpdate -= timePerFrame;

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

        if ( event.type == sf::Event::KeyPressed ) {
          if ( event.key.code == sf::Keyboard::Up )
            isMovingUp = true;
          else if ( event.key.code == sf::Keyboard::Down )
            isMovingDown = true;
          else if ( event.key.code == sf::Keyboard::Left )
            isMovingLeft = true;
          else if ( event.key.code == sf::Keyboard::Right )
            isMovingRight = true;
        }

        if ( event.type == sf::Event::KeyReleased ) {
          if ( event.key.code == sf::Keyboard::Up )
            isMovingUp = false;
          else if ( event.key.code == sf::Keyboard::Down )
            isMovingDown = false;
          else if ( event.key.code == sf::Keyboard::Left )
            isMovingLeft = false;
          else if ( event.key.code == sf::Keyboard::Right )
            isMovingRight = false;
        }
      }

      // update logic
      camera.setCenter( player.getPosition() );

      sf::Vector2f movement( 0.f, 0.f );
      if ( isMovingUp )
        movement.y -= playerSpeed;
      if ( isMovingDown )
        movement.y += playerSpeed;
      if ( isMovingLeft )
        movement.x -= playerSpeed;
      if ( isMovingRight )
        movement.x += playerSpeed;

      player.move( movement * timePerFrame.asSeconds());
    }

    // render
    window.setView( camera );

    window.clear();
    window.draw( background );
    window.draw( player );
    window.display();
  }
  return 0;
}
 
Title: Re: Jerky gameplay
Post by: Hapax on November 24, 2014, 12:17:50 am
I think I see what you mean by "jerky". This has been posted about on the forum before, actually. I'm not sure what the solution was, if there was one.

I have a request for you. Add this line of code:
window.setTitle("*");
(I put it before window.setView(camera);)
Let me know if anything changes.
Title: Re: Jerky gameplay
Post by: Jycerian on November 24, 2014, 09:52:07 am
I think I see what you mean by "jerky". This has been posted about on the forum before, actually. I'm not sure what the solution was, if there was one.

I have a request for you. Add this line of code:
window.setTitle("*");
(I put it before window.setView(camera);)
Let me know if anything changes.

Yeah I searched the forum but could't really find anything that would help me because everyone just tells em to enable v-sync..which I have. Also the setTitle did not change anything :C
Title: Re: Jerky gameplay
Post by: Nexus on November 24, 2014, 02:34:23 pm
Which version of SFML are you using? If it's not the latest revision from GitHub, please update it. There have been some changes to frame handling in the not-so-distant past.

And you should really reduce the example to a minimal one as much as you can. If this is a bug, we don't care about how the player moves or what textures are loaded... Since you say that Jesper's code shows the problem too, please reduce his code as much as possible.
Title: Re: Jerky gameplay
Post by: Hapax on November 24, 2014, 11:22:01 pm
everyone just tells em to enable v-sync..which I have.
If it's a problem that v-sync that could solve, it's possible that v-sync is not getting used. Remember that SFML just tells your graphics driver that it thinks it should use v-sync; it's up to your graphics card's drivers whether or not to listen (there are often settings to tell the driver to listen to apps - you may need to make sure they aren't getting overridden).

the setTitle did not change anything
No worries. I accidentally found that it almost perfectly displayed motion when the title was being set to the star but jumpy and jerky when it was being set to nothing, or not being set at all. Strange effect that I can't explain but I suspect it may be something to do with forcing something to update somewhere. I just don't know. Thanks for trying it, anyway  :D
Title: Re: Jerky gameplay
Post by: Jycerian on November 25, 2014, 09:58:48 am
everyone just tells em to enable v-sync..which I have.
If it's a problem that v-sync that could solve, it's possible that v-sync is not getting used. Remember that SFML just tells your graphics driver that it thinks it should use v-sync; it's up to your graphics card's drivers whether or not to listen (there are often settings to tell the driver to listen to apps - you may need to make sure they aren't getting overridden).

Thanks, didn't think about it that much. Checked my AMD settings and it's set to off unless specified by an application so that should be ok I suppose.
Title: Re: Jerky gameplay
Post by: Jycerian on December 10, 2014, 03:16:13 pm
Still have not resolved this problem. I have no clue what causes this. So here a very minimal example. It is harder to see with shapes instead of images but it is still there, some sort of image/sprite tearing (maby screen tearing but the background is not moving so can't confirm if it applies to everything) and sometimes it is a bit 'jerky'

EDIT: Updating SFML (10-12-2014) from GitHub also did not help.

#include <SFML/Graphics.hpp>

int main() {
  sf::RenderWindow window(sf::VideoMode(800, 600), "Jycerian", sf::Style::Close);
  window.setFramerateLimit(60);

  bool isMovingUp = false;
  bool isMovingDown = false;
  bool isMovingLeft = false;
  bool isMovingRight = false;

  sf::RectangleShape rect;
  rect.setSize(sf::Vector2f(32, 16));
  rect.setFillColor(sf::Color::Red);
  rect.setOutlineThickness(3);
  rect.setOutlineColor(sf::Color::Black);

  float moveSpeed = 100.f;

  sf::Clock clock;
  while (window.isOpen()) {
    sf::Event event;
    while (window.pollEvent(event)) {
      if (event.type == sf::Event::Closed)
        window.close();

      if (event.type == sf::Event::KeyPressed) {
        if (event.key.code == sf::Keyboard::W)
          isMovingUp = true;
        if (event.key.code == sf::Keyboard::S)
          isMovingDown = true;
        if (event.key.code == sf::Keyboard::A)
          isMovingLeft = true;
        if (event.key.code == sf::Keyboard::D)
          isMovingRight = true;
      }

      if (event.type == sf::Event::KeyReleased) {
        if (event.key.code == sf::Keyboard::W)
          isMovingUp = false;
        if (event.key.code == sf::Keyboard::S)
          isMovingDown = false;
        if (event.key.code == sf::Keyboard::A)
          isMovingLeft = false;
        if (event.key.code == sf::Keyboard::D)
          isMovingRight = false;
      }
    }

    sf::Vector2f velocity(0, 0);
    if (isMovingUp)
      velocity.y = -moveSpeed;
    if (isMovingDown)
      velocity.y = moveSpeed;
    if (isMovingLeft)
      velocity.x = -moveSpeed;
    if (isMovingRight)
      velocity.x = moveSpeed;

    rect.move(velocity * clock.restart().asSeconds());

    window.clear(sf::Color::White);
    window.draw(rect);
    window.display();
  }
}
Title: Re: Jerky gameplay
Post by: dabbertorres on December 10, 2014, 05:44:42 pm
Your example is not jerky on my machine.

You could try logging the time per frame and see if it ever jumps to a large or small amount than the average. Maybe your machine is having a hard time keep the framerate at 60fps?
Title: Re: Jerky gameplay
Post by: Jycerian on December 10, 2014, 10:38:46 pm
Your example is not jerky on my machine.

You could try logging the time per frame and see if it ever jumps to a large or small amount than the average. Maybe your machine is having a hard time keep the framerate at 60fps?

Yeah I will check that tomorrow and post back, do you experience any 'tearing' in the shape at any point?
Title: Re: Jerky gameplay
Post by: Jesper Juhl on December 10, 2014, 11:09:12 pm
Not sure it's relevant, but I saw the comment
Quote
Maybe your machine is having a hard time keep the framerate at 60fps?
and I just wanted to point out that; the first thing you should do (IMHO) is make your drawing independent of the actual frame rate, since it will fluctuate regardless of setFramerateLimit/setVerticalSyncEnabled or whatever you do yourself.
If you don't take a variable frame-rate into account (you really have to) you will see jerky movement.
If you haven't already read it, then the Fix Your Timestep (http://gafferongames.com/game-physics/fix-your-timestep/) article is a great place to start.
Title: Re: Jerky gameplay
Post by: dabbertorres on December 10, 2014, 11:18:55 pm
Your example is not jerky on my machine.

You could try logging the time per frame and see if it ever jumps to a large or small amount than the average. Maybe your machine is having a hard time keep the framerate at 60fps?

Yeah I will check that tomorrow and post back, do you experience any 'tearing' in the shape at any point?
Nope, looks fine.

And yep, that's where I was headed next in replying, Jesper!
Title: Re: Jerky gameplay
Post by: Jesper Juhl on December 10, 2014, 11:22:15 pm
And yep, that's where I was headed next in replying, Jesper!
Huh? I really don't know what to make of that..
Title: Re: Jerky gameplay
Post by: dabbertorres on December 11, 2014, 12:59:22 am
Sorry, I meant, that I assumed he'd ask how to solve separating the rendering and the logic, and then I was going to reply with something along the lines of what you replied with.
Title: Re: Jerky gameplay
Post by: Jycerian on December 11, 2014, 01:50:21 am
Hihi, no I know how to seperate the logic and render and to apply a fixed timestep. But again this does not resolve the issue. Maby its my machine? I am really not sure. It seems everyone else can run it just fine? I can play League of Legends on all low settings with 60 fps and super smooth, but can't have a square move across my screen without being sometimes 'jerky' and the 'tearing'. So weird.
Title: Re: Jerky gameplay
Post by: Jycerian on December 13, 2014, 02:22:11 pm
Your example is not jerky on my machine.

You could try logging the time per frame and see if it ever jumps to a large or small amount than the average. Maybe your machine is having a hard time keep the framerate at 60fps?

Timed my timestep with setFramerateLimit(60)
Title: Re: Jerky gameplay
Post by: dabbertorres on December 13, 2014, 05:31:42 pm
Hmm, looks fine to me. I'm not sure what to make of it.
Title: Re: Jerky gameplay
Post by: Jycerian on December 13, 2014, 11:08:36 pm
I am not sure if this will help but this is my DxDiag, anyone got an idea what causes the tearing and jerky movement?
Title: Re: Jerky gameplay
Post by: underww on December 14, 2014, 04:14:59 am
I think this is because of the floating numbers of the sprite's position.
Try to use an integer value for velocity.

For example


        if (isMovingUp)
                velocity.y = -1.f;
        if (isMovingDown)
                velocity.y = 1.f;
        if (isMovingLeft)
                velocity.x = -1.f;
        if (isMovingRight)
                velocity.x = 1.f;

        rect.move(velocity);
 
Title: Re: Jerky gameplay
Post by: Jycerian on December 14, 2014, 12:56:47 pm
How would you go about this using deltatime? Because that is a floating point number. In my example my player velocity.x would be something like 1.5.
Title: Re: Jerky gameplay
Post by: Hapax on December 14, 2014, 09:18:09 pm
How would you go about this using deltatime?
You could round() (http://www.cplusplus.com/reference/cmath/round/) or floor() (http://www.cplusplus.com/reference/cmath/floor/) the value when setting the sprite position if you want to keep it to an integer value.
This can improve the sprite's display quality but is more likely to cause jerky movement than to solve it.
Title: Re: Jerky gameplay
Post by: Jycerian on December 14, 2014, 09:43:00 pm
How would you go about this using deltatime?
You could round() (http://www.cplusplus.com/reference/cmath/round/) or floor() (http://www.cplusplus.com/reference/cmath/floor/) the value when setting the sprite position if you want to keep it to an integer value.
This can improve the sprite's display quality but is more likely to cause jerky movement than to solve it.
'

Alright, do you have any insight in my problem? You seem like a well established community member, ever stumbled across something like this?
Title: Re: Jerky gameplay
Post by: Hapax on December 15, 2014, 02:57:28 am
Unfortunately, I have unsure which exact problem you're getting and what its effect is. The code that causes you to have the problem doesn't seem to cause it for others so we can't see it. I suppose you could record a video of it but it's possible that it wouldn't capture the "jerkiness", or may even create some of its own.

As you may've also noticed, the word jerky is slightly ambiguous.
Title: Re: Jerky gameplay
Post by: underww on December 15, 2014, 03:22:33 am
I heard that old games like Super Mario Bros stored subpixels in a separate integer.
So you might also use an another variable for the decimal units of the velocity.
But I don't know this is good for modern game dev or not.

as I know on it is also a kind of limit of pure 2D graphics.
You need to use 3D graphics (means directly use OpenGL) to solve this problem completely.
Title: Re: Jerky gameplay
Post by: Jycerian on December 15, 2014, 10:20:18 am
Well let me try to explain it in more detail:

When I stand still there is no problem, no flashy things or screen tearing (only visible on the sprite.) When I move the character it moves in the given direction but then it becomes slightly jerky like it seems to skip a couple of pixels so it isn't smooth maybe because it skips a couple of frames? Or just skips the pixels in general maybe due to using floats? Also another effect appears where it looks like the Sprite is tearing for instance when I move to the right the top half would be something like 2 pixels to the left and the bottom half 2 pixels to the right and then it becomes normal again. It seems this tearing and jerkiness appear at random intervals.

It seems like other people have no problems with my code? I have updated SFML and my graphics driver so maybe it is a bug that has to do this the support of my video-card / processor? Games like League of Legends run fine for instance. I posted my computer stats in an earlier post.
Title: Re: Jerky gameplay
Post by: Hapax on December 15, 2014, 03:34:20 pm
It sounds like you're having two issues. One with tearing, and another with skipping.
The tearing can only (as far as I'm aware) be fixed by using vertical sync.. Unfortunately, the graphics card is in charge of that and its drivers are in charge of that card so they could easily be ignoring SFML's request for v-sync.
The skipping does sound like it's skipping frames; it's been mentioned on the forum a few times already and I've seen it on my own projects. You should make sure you've tried a release build instead of a debug build first as that often makes a difference.
You also mentioned that it could be skipping pixels because of using floats. I don't think floats would directly be the cause. It would only be if the two draw positions are two pixels apart. If you're rounding and the two positions are 2.49 and 3.5 (distance of about 1), the rounded positions would be 2 and 4 (distance of 2).

Comparing with League Of Legends is an odd thing to do. It's rendering in 3D for a start  :P
Title: Re: Jerky gameplay
Post by: Jycerian on December 15, 2014, 05:46:07 pm
Thanks for the input, just tested without frame-rate limit and then it is pretty much smooth and the tearing doesnt happen that often. Also the borders of the square become kinda fuzzy when moving and sharp when not moving but that is because you are moving using floating points I guess. So it seems like the program is skipping frames, is this normal or is it just me?
Title: Re: Jerky gameplay
Post by: Jesper Juhl on December 15, 2014, 06:13:12 pm
Thanks for the input, just tested without frame-rate limit
You should never use both vsync and frame-rate limit both in the same program. They interact badly and if that's what you were doing (which I get the impression you were, since vsync is usually the best way to counter tearing), it is not surprising that you were having issues. This is well documented btw.
Title: Re: Jerky gameplay
Post by: Jycerian on December 15, 2014, 11:05:53 pm
Thanks for the input, just tested without frame-rate limit
You should never use both vsync and frame-rate limit both in the same program. They interact badly and if that's what you were doing (which I get the impression you were, since vsync is usually the best way to counter tearing), it is not surprising that you were having issues. This is well documented btw.

I know about this, I am not using both, enabling v-sync doesn't work for me anyways even though my display driver is setup properly.