Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Jittery 98 sprites  (Read 1860 times)

0 Members and 1 Guest are viewing this topic.

MichelangeloSFML/

  • Newbie
  • *
  • Posts: 17
    • View Profile
Jittery 98 sprites
« on: August 15, 2022, 02:10:30 pm »
I have a vector<Sprites> with 98 elements (300x200 at scale (.5,.5)) and I am trying to move them all in the x-axis. I also have in the update section:
Time dt = clock.restart();

The sprites move very nicely with uncapped framerate, but they become jittery when I set:
window.setFramerateLimit(60);

Even though the FPS remains at constant above 60 (61-62). Any solutions or help would be appreciated.


Code: [Select]
if (m_MovingLeft)
{
for (int i = 0; i < m_Array.size(); ++i)
{
m_Array[i].setPosition(m_Array[i].getGlobalBounds().left - m_SpeedMoving * dt.asSeconds(), m_Array[i].getGlobalBounds().top);
}
}

if (m_MovingRight)
{
for (int i = 0; i < m_Array.size(); ++i)
{
m_Array[i].setPosition(m_Array[i].getGlobalBounds().left + m_SpeedMoving * dt.asSeconds(), m_Array[i].getGlobalBounds().top);
}
}
« Last Edit: August 15, 2022, 02:14:01 pm by MichelangeloSFML/ »

Stauricus

  • Sr. Member
  • ****
  • Posts: 369
    • View Profile
    • A Mafia Graphic Novel
    • Email
Re: Jittery 98 sprites
« Reply #1 on: August 15, 2022, 04:46:19 pm »
do you have v-sync activated? v-sync and setFramerateLimit don't work well together.
Visit my game site (and hopefully help funding it? )
Website | IndieDB

MichelangeloSFML/

  • Newbie
  • *
  • Posts: 17
    • View Profile
Re: Jittery 98 sprites
« Reply #2 on: August 16, 2022, 07:41:09 am »
I only use:
window.setFramerateLimit(60);

The sprites move & then there is a quick micro second pause & then move again, & it is not consistent. Sometimes it can even pause/jitter twice, but more rarely. Sometimes it can move for longer periods and not jitter/pause.

When I try 50 sprite elements it runs smoother & jitters less frequently, 30 elements runs even smoother & barely jitters. BUT even with 30 if I hit L/R/L/R/L/R quickly & then hold R it is guaranteed to jitter. Stop holding the keys for a second & start again & it runs smooth again, as if the system is trying to catch up. Is there a container that is quicker than a vector<Sprite>, although a vector should be good enough since all my Sprites are loaded on startup & I never add/remove any throughout the game. Maybe that is the issue or is it the window.draw() for too many elements?

My key presses & releases are controlled with a bool in the class.
Code: [Select]
        if (Keyboard::isKeyPressed(Keyboard::Left))
        {
            classSprite.moveLeft();
        }
        else
        {
             classSprite.stopLeft();
        }

        if (Keyboard::isKeyPressed(Keyboard::Right))
        {
            classSprite.moveRight();
        }
        else
        {
            classSprite.stopRight();
        }
« Last Edit: August 17, 2022, 12:24:23 am by MichelangeloSFML/ »

MichelangeloSFML/

  • Newbie
  • *
  • Posts: 17
    • View Profile
Re: Jittery 98 sprites
« Reply #3 on: August 16, 2022, 11:42:21 pm »
I have tried so many things, including:

1) Implementing keyboard input from the Event event.key.code instead.
2) Inserting a break in the for loops when button isKeyReleased.
3) Moving the vector to main().
4) Trying various other frame rates: 30,60,120,240
5) Removing all other items except the vector & sprites in question.

Today I learned since dt is not consistently the same that it might be wise to check & force dt to consistency, so I am going to give this a try:

const float dt60 = 1.0f / 60.0f;
if (dt > dt60)
     dt -= dt60;
« Last Edit: August 16, 2022, 11:45:54 pm by MichelangeloSFML/ »

MichelangeloSFML/

  • Newbie
  • *
  • Posts: 17
    • View Profile
Re: Jittery 98 sprites
« Reply #4 on: August 17, 2022, 11:24:56 am »
I now tried to implement fixed time steps as suggested in the book SFML Game Development on p23, but it actually seems to be worst now & I cannot get even 2 sprites to scroll without jitter.

I must be doing something wrong, or it is the vector<Sprite> that is the problem. I rewrote the code outside of any classes in order to show it. Picture is 200x300 & array in code is set to 2x1 = (2 images to display).

Code: [Select]
#include <iostream>
#include<vector>
#include <SFML/Graphics.hpp>
#include <SFML/Audio.hpp>

using namespace sf;
using namespace std;

vector<Sprite> spriteArray;
float m_SpeedMoving = 600.0f;

const int numVertical = 2;      //Number of vertical sprites to create
const int numHorizontal = 1;    //Number of horizontal sprites to create

const int OffsetBottom = 20;
const int OffsetBottomOfScreen = 100;
const int OffsetLeft = 40;

void MakeSpriteArray(Texture& texture)
{
    unsigned short colCounter = 0;
    unsigned short numVert = 0;

    for (int i = 0; i < (numVertical * numHorizontal); ++i)
    {
        spriteArray.push_back(Sprite());
        spriteArray[i].setTexture(texture);            
        spriteArray[i].setScale(0.5, 0.5);

        if (colCounter == 0) //First column of sprite
        {
            if (numVert == 0) //Bottom row of sprites just above the bottom of the screen
            {
                spriteArray[i].setPosition(0, (1080 - OffsetBottomOfScreen) - spriteArray[i].getGlobalBounds().height);
            }
            else
            {
                spriteArray[i].setPosition(0, spriteArray[i - 1].getGlobalBounds().top - (spriteArray[i].getGlobalBounds().height - OffsetBottom));
            }
        }
        else
        {
            if (numVert == 0) //Bottom row of sprites just above the bottom of the screen
            {
                spriteArray[i].setPosition((spriteArray[i - numVertical].getGlobalBounds().left + spriteArray[i - numVertical].getGlobalBounds().width - OffsetLeft),
                    (1080 - OffsetBottomOfScreen) - spriteArray[i].getGlobalBounds().height);
            }
            else
            {
                spriteArray[i].setPosition((spriteArray[i - numVertical].getGlobalBounds().left + (spriteArray[i - numVertical].getGlobalBounds().width - OffsetLeft)),
                    (spriteArray[i - 1].getGlobalBounds().top - spriteArray[i].getGlobalBounds().height) + OffsetBottom);
            }
        }

        ++numVert;
        if (numVert == numVertical)
        {
            ++colCounter;
            numVert = 0;
        }
    }
}

void MoveLeft(Time& TIME_PER_FRAME)
{
    for (int i = 0; i < spriteArray.size(); ++i)
    {
        //spriteArray[i].setPosition(spriteArray[i].getGlobalBounds().left - m_SpeedMoving * dt.asSeconds(),
        //    spriteArray[i].getGlobalBounds().top);
        spriteArray[i].setPosition(spriteArray[i].getGlobalBounds().left - m_SpeedMoving * TIME_PER_FRAME.asSeconds(),
            spriteArray[i].getGlobalBounds().top);

        //if (!Keyboard::isKeyPressed(Keyboard::Left))
        //    break;
    }
}

void MoveRight(Time& TIME_PER_FRAME)
{
    for (int i = 0; i < spriteArray.size(); ++i)
    {
        //spriteArray[i].setPosition(spriteArray[i].getGlobalBounds().left + m_SpeedMoving * dt.asSeconds(),
        //    spriteArray[i].getGlobalBounds().top);

        spriteArray[i].setPosition(spriteArray[i].getGlobalBounds().left + m_SpeedMoving * TIME_PER_FRAME.asSeconds(),
            spriteArray[i].getGlobalBounds().top);

        //if (!Keyboard::isKeyPressed(Keyboard::Right))
        //    break;
    }
}


int main()
{
    //******************  WINDOW ******************
    Vector2f resolution;
    resolution.x = VideoMode::getDesktopMode().width;
    resolution.y = VideoMode::getDesktopMode().height;

    VideoMode vm(resolution.x, resolution.y);

    RenderWindow window(vm, "TEST", Style::Default);
    window.setFramerateLimit(60);

    Texture texture;
    texture.loadFromFile("graphics/Image1.png");



    //******************  TEXT  ******************



    //****************** CONFIG  ******************
    Clock clock;

    Time timeSinceLastUpdate = Time::Zero;
    Time TIME_PER_FRAME = seconds(1.0f / 60.0f);
   
    MakeSpriteArray(texture);

    bool isMovingLeft = false;
    bool isMovingRight = false;

    while (window.isOpen())
    {
        //**********************************************************
        //*******************   KEYBOARD/MOUSE   *******************
        //**********************************************************
        Event event;                       

        //NEEDED, to prevent intial screen blue circle
        while (window.pollEvent(event))
        {

        }

        //ESC to exit game
        if (Keyboard::isKeyPressed(Keyboard::Escape))
            window.close();


        ////*******************   KEYS   *******************

        if (Keyboard::isKeyPressed(Keyboard::Left))
        {
            isMovingLeft = true;
        }
        else
        {
            isMovingLeft = false;
        }

        if (Keyboard::isKeyPressed(Keyboard::Right))
        {
            isMovingRight = true;
        }
        else
        {
            isMovingRight = false;
        }


        //**********************************************************
        //*******************       UPDATE       *******************
        //**********************************************************
       
        timeSinceLastUpdate += clock.restart();
        //Time dt = clock.restart();

        cout << TIME_PER_FRAME.asSeconds() << endl;

        while (timeSinceLastUpdate > TIME_PER_FRAME)
        {
            timeSinceLastUpdate -= TIME_PER_FRAME;

            if (isMovingLeft)
            {
                MoveLeft(TIME_PER_FRAME);

            }

            if (isMovingRight)
            {
                MoveRight(TIME_PER_FRAME);
            }
        }

        //**********************************************************
        //*******************       DRAW         *******************
        //**********************************************************
        window.clear();

        //DRAW ALL
        for (int i = spriteArray.size() - 1; i >= 0; --i)       
        {
            window.draw(spriteArray[i]);
        }
        window.display();
    }

    return 0;
}


MichelangeloSFML/

  • Newbie
  • *
  • Posts: 17
    • View Profile
Re: Jittery 98 sprites
« Reply #5 on: August 17, 2022, 01:11:44 pm »
I removed the vector<Sprite> from this one & implemented them as individual objects and yet still it jitters, so it is not the vector. I cannot even get 1 image to move across without stuttering/jitttering at one point or another at 60FPS.

I tried the method from the book & I also tried the method where you just multiply by good old dt.asSeconds() & still the same. I even tried setting a FloatRectangle to the getGlobalBounds() & then setPosition() and still no go.

Code: [Select]
#include <iostream>
#include<vector>
#include <SFML/Graphics.hpp>
#include <SFML/Audio.hpp>

using namespace sf;
using namespace std;

float m_SpeedMoving = 600.0f;

int main()
{
    //******************  WINDOW ******************
    Vector2f resolution;
    resolution.x = VideoMode::getDesktopMode().width;
    resolution.y = VideoMode::getDesktopMode().height;

    VideoMode vm(resolution.x, resolution.y);

    RenderWindow window(vm, "TEST", Style::Default);
    window.setFramerateLimit(60);


    //******************    ******************
    Texture texture;
    texture.loadFromFile("graphics/Image1.png");

    Sprite sprite1;
    sprite1.setTexture(texture);
    sprite1.setScale(.5, .5);
    sprite1.setPosition(0, 400);
   
    Sprite sprite2;
    sprite2.setTexture(texture);
    sprite2.setScale(.5, .5);
    sprite2.setPosition(0, 480);

    Sprite sprite3;
    sprite3.setTexture(texture);
    sprite3.setScale(.5, .5);
    sprite3.setPosition(0, 560);

    Sprite sprite4;
    sprite4.setTexture(texture);
    sprite4.setScale(.5, .5);
    sprite4.setPosition(0, 640);

    Sprite sprite5;
    sprite5.setTexture(texture);
    sprite5.setScale(.5, .5);
    sprite5.setPosition(0, 720);


    //FloatRect RectFloatSprite1 = sprite1.getGlobalBounds();
    //FloatRect RectFloatSprite2 = sprite2.getGlobalBounds();
    //FloatRect RectFloatSprite3 = sprite3.getGlobalBounds();
    //FloatRect RectFloatSprite4 = sprite4.getGlobalBounds();
    //FloatRect RectFloatSprite5 = sprite5.getGlobalBounds();
    //FloatRect RectFloatSprite = sprite.getGlobalBounds();



    //******************  TEXT  ******************



    //****************** CONFIG  ******************
    Clock clock;

    Time timeSinceLastUpdate = Time::Zero;
    Time TIME_PER_FRAME = seconds(1.0f / 60.0f);
   

    bool isMovingLeft = false;
    bool isMovingRight = false;

    while (window.isOpen())
    {
        //**********************************************************
        //*******************   KEYBOARD/MOUSE   *******************
        //**********************************************************
        Event event;                       

        //NEEDED, to prevent intial screen blue circle
        while (window.pollEvent(event))
        {

        }

        //ESC to exit game
        if (Keyboard::isKeyPressed(Keyboard::Escape))
            window.close();


        ////*******************   KEYS   *******************
        //Time dt = clock.restart();

        if (Keyboard::isKeyPressed(Keyboard::Left))
        {
            isMovingLeft = true;

            //sprite1.setPosition(sprite1.getPosition().x - m_SpeedMoving * dt.asSeconds(), sprite1.getPosition().y);
            //sprite2.setPosition(sprite2.getPosition().x - m_SpeedMoving * dt.asSeconds(), sprite2.getPosition().y);
            //sprite3.setPosition(sprite3.getPosition().x - m_SpeedMoving * dt.asSeconds(), sprite3.getPosition().y);
            //sprite4.setPosition(sprite4.getPosition().x - m_SpeedMoving * dt.asSeconds(), sprite4.getPosition().y);
            //sprite5.setPosition(sprite5.getPosition().x - m_SpeedMoving * dt.asSeconds(), sprite5.getPosition().y);

            //RectFloatSprite1.left = RectFloatSprite1.left - m_SpeedMoving * dt.asSeconds();
            //RectFloatSprite2.left = RectFloatSprite2.left - m_SpeedMoving * dt.asSeconds();
            //RectFloatSprite3.left = RectFloatSprite3.left - m_SpeedMoving * dt.asSeconds();
            //RectFloatSprite4.left = RectFloatSprite4.left - m_SpeedMoving * dt.asSeconds();
            //RectFloatSprite5.left = RectFloatSprite5.left - m_SpeedMoving * dt.asSeconds();
            ////RectFloatSprite.left = RectFloatSprite.left - m_SpeedMoving * dt.asSeconds();

            //sprite1.setPosition(RectFloatSprite1.left, RectFloatSprite1.top);
            //sprite2.setPosition(RectFloatSprite2.left, RectFloatSprite2.top);
            //sprite3.setPosition(RectFloatSprite3.left, RectFloatSprite3.top);
            //sprite4.setPosition(RectFloatSprite4.left, RectFloatSprite4.top);
            //sprite5.setPosition(RectFloatSprite5.left, RectFloatSprite5.top);
            //sprite.setPosition(RectFloatSprite.left, RectFloatSprite.top);
        }
        else
        {
            isMovingLeft = false;
        }

        if (Keyboard::isKeyPressed(Keyboard::Right))
        {
            isMovingRight = true;

            //sprite1.setPosition(sprite1.getPosition().x + m_SpeedMoving * dt.asSeconds(), sprite1.getPosition().y);
            //sprite2.setPosition(sprite2.getPosition().x + m_SpeedMoving * dt.asSeconds(), sprite2.getPosition().y);
            //sprite3.setPosition(sprite3.getPosition().x + m_SpeedMoving * dt.asSeconds(), sprite3.getPosition().y);
            //sprite4.setPosition(sprite4.getPosition().x + m_SpeedMoving * dt.asSeconds(), sprite4.getPosition().y);
            //sprite5.setPosition(sprite5.getPosition().x + m_SpeedMoving * dt.asSeconds(), sprite5.getPosition().y);

            //RectFloatSprite1.left = RectFloatSprite1.left + m_SpeedMoving * dt.asSeconds();
            //RectFloatSprite2.left = RectFloatSprite2.left + m_SpeedMoving * dt.asSeconds();
            //RectFloatSprite3.left = RectFloatSprite3.left + m_SpeedMoving * dt.asSeconds();
            //RectFloatSprite4.left = RectFloatSprite4.left + m_SpeedMoving * dt.asSeconds();
            //RectFloatSprite5.left = RectFloatSprite5.left + m_SpeedMoving * dt.asSeconds();
            ////RectFloatSprite.left = RectFloatSprite.left + m_SpeedMoving * dt.asSeconds();

            //sprite1.setPosition(RectFloatSprite1.left, RectFloatSprite1.top);
            //sprite2.setPosition(RectFloatSprite2.left, RectFloatSprite2.top);
            //sprite3.setPosition(RectFloatSprite3.left, RectFloatSprite3.top);
            //sprite4.setPosition(RectFloatSprite4.left, RectFloatSprite4.top);
            //sprite5.setPosition(RectFloatSprite5.left, RectFloatSprite5.top);
            //sprite.setPosition(RectFloatSprite.left, RectFloatSprite.top);
        }
        else
        {
            isMovingRight = false;
        }

        //**********************************************************
        //*******************       UPDATE       *******************
        //**********************************************************
       
        timeSinceLastUpdate += clock.restart();
        //Time dt = clock.restart();

        //cout << TIME_PER_FRAME.asSeconds() << endl;

        while (timeSinceLastUpdate > TIME_PER_FRAME)
        {
            timeSinceLastUpdate -= TIME_PER_FRAME;

            if (isMovingLeft)
            {
                sprite1.setPosition(sprite1.getPosition().x - m_SpeedMoving * TIME_PER_FRAME.asSeconds(), sprite1.getPosition().y);
                //sprite2.setPosition(sprite2.getPosition().x - m_SpeedMoving * TIME_PER_FRAME.asSeconds(), sprite2.getPosition().y);
                //sprite3.setPosition(sprite3.getPosition().x - m_SpeedMoving * TIME_PER_FRAME.asSeconds(), sprite3.getPosition().y);
                //sprite4.setPosition(sprite4.getPosition().x - m_SpeedMoving * TIME_PER_FRAME.asSeconds(), sprite4.getPosition().y);
                //sprite5.setPosition(sprite5.getPosition().x - m_SpeedMoving * TIME_PER_FRAME.asSeconds(), sprite5.getPosition().y);

                //RectFloatSprite1.left = RectFloatSprite1.left - m_SpeedMoving * TIME_PER_FRAME.asSeconds();
                //RectFloatSprite2.left = RectFloatSprite2.left - m_SpeedMoving * TIME_PER_FRAME.asSeconds();
                //RectFloatSprite3.left = RectFloatSprite3.left - m_SpeedMoving * TIME_PER_FRAME.asSeconds();
                //RectFloatSprite4.left = RectFloatSprite4.left - m_SpeedMoving * TIME_PER_FRAME.asSeconds();
                //RectFloatSprite5.left = RectFloatSprite5.left - m_SpeedMoving * TIME_PER_FRAME.asSeconds();
                ////RectFloatSprite.left = RectFloatSprite.left - m_SpeedMoving * TIME_PER_FRAME.asSeconds();

                //sprite1.setPosition(RectFloatSprite1.left, RectFloatSprite1.top);
                //sprite2.setPosition(RectFloatSprite2.left, RectFloatSprite2.top);
                //sprite3.setPosition(RectFloatSprite3.left, RectFloatSprite3.top);
                //sprite4.setPosition(RectFloatSprite4.left, RectFloatSprite4.top);
                //sprite5.setPosition(RectFloatSprite5.left, RectFloatSprite5.top);
                //sprite.setPosition(RectFloatSprite.left, RectFloatSprite.top);

            }

            if (isMovingRight)
            {
                sprite1.setPosition(sprite1.getPosition().x + m_SpeedMoving * TIME_PER_FRAME.asSeconds(), sprite1.getPosition().y);
                //sprite2.setPosition(sprite2.getPosition().x + m_SpeedMoving * TIME_PER_FRAME.asSeconds(), sprite2.getPosition().y);
                //sprite3.setPosition(sprite3.getPosition().x + m_SpeedMoving * TIME_PER_FRAME.asSeconds(), sprite3.getPosition().y);
                //sprite4.setPosition(sprite4.getPosition().x + m_SpeedMoving * TIME_PER_FRAME.asSeconds(), sprite4.getPosition().y);
                //sprite5.setPosition(sprite5.getPosition().x + m_SpeedMoving * TIME_PER_FRAME.asSeconds(), sprite5.getPosition().y);

                //RectFloatSprite1.left = RectFloatSprite1.left + m_SpeedMoving * TIME_PER_FRAME.asSeconds();
                //RectFloatSprite2.left = RectFloatSprite2.left + m_SpeedMoving * TIME_PER_FRAME.asSeconds();
                //RectFloatSprite3.left = RectFloatSprite3.left + m_SpeedMoving * TIME_PER_FRAME.asSeconds();
                //RectFloatSprite4.left = RectFloatSprite4.left + m_SpeedMoving * TIME_PER_FRAME.asSeconds();
                //RectFloatSprite5.left = RectFloatSprite5.left + m_SpeedMoving * TIME_PER_FRAME.asSeconds();
                ////RectFloatSprite.left = RectFloatSprite.left + m_SpeedMoving * TIME_PER_FRAME.asSeconds();

                //sprite1.setPosition(RectFloatSprite1.left, RectFloatSprite1.top);
                //sprite2.setPosition(RectFloatSprite2.left, RectFloatSprite2.top);
                //sprite3.setPosition(RectFloatSprite3.left, RectFloatSprite3.top);
                //sprite4.setPosition(RectFloatSprite4.left, RectFloatSprite4.top);
                //sprite5.setPosition(RectFloatSprite5.left, RectFloatSprite5.top);
                //sprite.setPosition(RectFloatSprite.left, RectFloatSprite.top);
            }
        }

        //**********************************************************
        //*******************       DRAW         *******************
        //**********************************************************
        window.clear();

        window.draw(sprite1);
        //window.draw(sprite2);
        //window.draw(sprite3);
        //window.draw(sprite4);
        //window.draw(sprite5);
        //window.draw(sprite);

        window.display();
    }

    return 0;
}

« Last Edit: August 17, 2022, 01:16:41 pm by MichelangeloSFML/ »

MichelangeloSFML/

  • Newbie
  • *
  • Posts: 17
    • View Profile
Re: Jittery 98 sprites
« Reply #6 on: August 18, 2022, 09:52:42 am »
Here is code with only 1 image & still the same problem of jittery movement.

#include <iostream>
#include <SFML/Graphics.hpp>
#include <SFML/Audio.hpp>

using namespace sf;
using namespace std;

int main()
{
    //******************  WINDOW ******************
    Vector2f resolution;
    resolution.x = VideoMode::getDesktopMode().width;
    resolution.y = VideoMode::getDesktopMode().height;

    VideoMode vm(resolution.x, resolution.y);

    RenderWindow window(vm, "TEST", Style::Default);
    window.setFramerateLimit(60);


    //****************** TEXTURES/SPRITES   ******************
    Texture texture;
    texture.loadFromFile("graphics/Image1.png");

    Sprite sprite1;
    sprite1.setTexture(texture);
    sprite1.setScale(.5, .5);
    sprite1.setPosition(0, 400);



    //******************  TEXT  ******************



    //****************** CONFIG  ******************
    Clock clock;

    Time timeSinceLastUpdate = Time::Zero;
    const Time TIME_PER_FRAME = seconds(1.0f / 60.0f);

    const float SPEED_MOVING = 600.0f;

    while (window.isOpen())
    {
        //**********************************************************
        //*******************   KEYBOARD/MOUSE   *******************
        //**********************************************************
        Event event;

        while (window.pollEvent(event))
        {

        }

        //ESC to exit game
        if (Keyboard::isKeyPressed(Keyboard::Escape))
            window.close();

        //**********************************************************
        //*******************       UPDATE       *******************
        //**********************************************************

        timeSinceLastUpdate += clock.restart();
     
        //cout << TIME_PER_FRAME.asSeconds() << endl;

        while (timeSinceLastUpdate > TIME_PER_FRAME)
        {
            timeSinceLastUpdate -= TIME_PER_FRAME;


            if (sprite1.getGlobalBounds().left < -200)
            {
                sprite1.setPosition(2040 , sprite1.getPosition().y);
            }

            sprite1.setPosition(sprite1.getPosition().x - SPEED_MOVING * TIME_PER_FRAME.asSeconds(), sprite1.getPosition().y);
        }

        //**********************************************************
        //*******************       RENDER        *******************
        //**********************************************************
        window.clear();

        window.draw(sprite1);

        window.display();
    }

    return 0;
}

 

fallahn

  • Sr. Member
  • ****
  • Posts: 492
  • Buns.
    • View Profile
    • Trederia
Re: Jittery 98 sprites
« Reply #7 on: August 18, 2022, 10:41:22 am »
Are you testing this in a release build, or is this only in debug?
Also do you have an nvidia card? You could try disabling Threaded Optimisation: https://en.sfml-dev.org/forums/index.php?topic=23708.msg161792#msg161792

MichelangeloSFML/

  • Newbie
  • *
  • Posts: 17
    • View Profile
Re: Jittery 98 sprites
« Reply #8 on: August 18, 2022, 06:21:47 pm »
Thanks. I am testing in debug mode.

I had already tried the NVidia threaded optimization to off & still the same jittery results. What does work for me is vsync on & 120HZ and my tv set to VRR, but not vsync on & 60HZ.

With vsync on & 120HZ I am able to render all the sprites without any jitter. But I would love to be able to get 60FPS to work without vsync & tv on 60HZ (no VRR).

My video card: GTX 1050 Ti
My tv: Sony - 43" class X85J 4K Model:KD43X85J
HDMI on input 3 (eARC/ARC)

When I wake up later I will try another input on my tv.
« Last Edit: August 18, 2022, 06:37:39 pm by MichelangeloSFML/ »

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 10801
    • View Profile
    • development blog
    • Email
Re: Jittery 98 sprites
« Reply #9 on: August 19, 2022, 04:39:52 am »
Our eyes & brain are very good at noticing small inconsistencies, which are perceived as stutter.
This could be that the movement of a sprite is off by a single pixel due to some rounding or timing issue.

To mitigate this, it's crucial to have a rock solid, frame independent, fixed-timestep physics calculation, including interpolations. That way you can ensure, no matter the fluctuation in rendering performance (drop of frames), that the calculated position and progress on the screen is accurate over time.
See also https://gafferongames.com/post/fix_your_timestep/

The second component is to make sure the rasterizer isn't causing troubles. When you render on non-integer positions (e.g. (2.3px, 5.3px)), then OpenGL has to make a decision on how to place/render your texture exactly. It can then happen to render to multiple pixels, approximating the overall look, i.e. rasterizing, which can in some cases lead to perceived stuttering, as the movement may not appear very smooth over multiple frames.
One solution is to render things only on integer positions, but that's not always possible, e.g. when an object should move rather slow.
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

MichelangeloSFML/

  • Newbie
  • *
  • Posts: 17
    • View Profile
Re: Jittery 98 sprites
« Reply #10 on: August 21, 2022, 11:19:21 am »
Thank you sir, I took a quick glance at the link & it looks like it is what I may need exactly.

I have to say that at vsync on & 120HZ (VRR) the 98 images are handled phenomenally on the system. Now I also tried drawing 300+ that are off the screen to the left & right and I did not see a performance hit. How does SFML handle sprites that are drawn off screen?  Images off screen are not really drawn, but only the setPosition calculations are performed or are they actually drawn?

It is hard to believe I don't get a dip in FPS or image stability of the 98 middle images that I do see when I include 100+ images drawn off screen to the L & R (300+ images).
« Last Edit: August 21, 2022, 11:26:57 am by MichelangeloSFML/ »

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 10801
    • View Profile
    • development blog
    • Email
Re: Jittery 98 sprites
« Reply #11 on: August 22, 2022, 03:46:23 am »
The vertex data is still being sent to the GPU, but then it's essentially up to the GPU to detect that it's offscreen and doesn't need to be rendered.
So if you have a large set of vertex data (e.g. a huge tilemap) then you can potentially still notice a dip in FPS, even if its offscreen.

SFML however also handles quite a few images on modern hardware without breaking a sweat.
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/