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

Author Topic: Jittering/Shaking sprites when moving with 'forces'  (Read 9803 times)

0 Members and 1 Guest are viewing this topic.

AndrewB

  • Newbie
  • *
  • Posts: 33
    • View Profile
Jittering/Shaking sprites when moving with 'forces'
« on: February 02, 2013, 10:49:55 am »
Hello everyone,

As I'm working on a basic platformer to hone my programming skills I've noticed that my player sprite jitters or shakes as I'm moving.

The current method of moving the sprite is as follows (minimal code example):
// player.hpp
class player : public sf::Spite
{
public:
   player();

   void update();

   sf::Vector2f forces;
};

// player.cpp
player::player()
{
   forces = sf::Vector2f(0.f, 0.f);
}

player::update()
{
   if (sf::Keyboard::isKeyDown(sf::Keyboard::Left)
   {
      forces.x += 0.1f;
   }
   if (sf::Keyboard::isKeyDown(sf::Keyboard::Right)
   {
      forces.x -= 0.1f;
   }

   // friction
   forces.x *= 0.9f;

   move(forces);
}
 

player.update() is called every frame.

It's not just when it's accelerating/decelerating, it seems like it's every second.

Is it because the forces is stored as a float and the precision of the float is causing it to move weirdly on some specific cases?

Thanks for any help, If you know of a better way of controlling sprite movement please let me know.
« Last Edit: February 02, 2013, 01:44:00 pm by AndrewB »

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Re: Jittering/Shaking sprites when moving with 'forces'
« Reply #1 on: February 02, 2013, 12:33:47 pm »
You should measure the time passed per frame and multiply the velocity with it. Also, some other tips:
  • Don't inherit sf::Sprite. Your player is not a sprite, he contains one.
  • The statement in your constructor has no effect, you declare a local variable.
  • For functions and blocks, there is no ; after } necessary.
  • You can use sf::Sprite::move().
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

AndrewB

  • Newbie
  • *
  • Posts: 33
    • View Profile
Re: Jittering/Shaking sprites when moving with 'forces'
« Reply #2 on: February 02, 2013, 01:51:00 pm »
You should measure the time passed per frame and multiply the velocity with it. Also, some other tips:
  • Don't inherit sf::Sprite. Your player is not a sprite, he contains one.
  • The statement in your constructor has no effect, you declare a local variable.
  • For functions and blocks, there is no ; after } necessary.
  • You can use sf::Sprite::move().

How do I go about changing the velocity of the player then? Won't changing the velocity from 1 to -1 cause the sprite to jump from one side of the screen to the other?

How are gravity and friction factored into the velocity? How about acceleration and deceleration?

As to your list;
1. I have player inherit sf::Sprite because of the way I draw the game using an ordered list of many different objects that are all sub-classes of sf::Sprite.
2. That was a miss type, this is not code from my game - I wrote this as an example.
3. A little style habit of mine. My OCD kills me if I see } without a ;.
4. Thanks, I've updated the code in the original post.
« Last Edit: February 02, 2013, 01:52:57 pm by AndrewB »

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Re: Jittering/Shaking sprites when moving with 'forces'
« Reply #3 on: February 02, 2013, 03:08:55 pm »
Quote from: AndrewB
How do I go about changing the velocity of the player then?
You measure the frame time dt with sf::Clock. Then, you offset the position according to the velocity multiplied with the passed time:
sf::Vector2f velocity = getVelocityFromInput();
sf::Vector2f offset = velocity * dt.asSeconds();
sprite.move(offset);

Quote from: AndrewB
Won't changing the velocity from 1 to -1 cause the sprite to jump from one side of the screen to the other?
No, it will revert the direction.

Quote from: AndrewB
How are gravity and friction factored into the velocity? How about acceleration and deceleration?
All can be modeled as an acceleration which is continuously added to the velocity. The simplest case is just Euler integration:
const float friction = ...;
const float gravity = ...;

sf::Vector2f acceleration;
acceleration.x = onGround ? -friction * velocity.x : 0.f;
acceleration.y = gravity;

velocity += acceleration * dt.asSeconds();

This should work for most cases. If it's not accurate enough, you could have a look at the articles about RK4 integration and fixed timestep.

Quote from: AndrewB
I have player inherit sf::Sprite because of the way I draw the game using an ordered list of many different objects that are all sub-classes of sf::Sprite.
Yes, but why are they subclasses of sf::Sprite? That is an unnecessary coupling and restriction. The classes should rather derive from sf::Drawable (and maybe sf::Transformable) and hold a sf::Sprite as a member. Like this, you can easily change the representation, like drawing multiple sprites for an object, or drawing a shape. This is not possible with your current approach.

Also, sf::Sprite is not designed as a polymorphic base class, for example you can't have your own virtual functions that describe the object's behavior.
« Last Edit: February 02, 2013, 03:10:55 pm by Nexus »
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

AndrewB

  • Newbie
  • *
  • Posts: 33
    • View Profile
Re: Jittering/Shaking sprites when moving with 'forces'
« Reply #4 on: February 03, 2013, 01:01:14 am »
You measure the frame time dt with sf::Clock. Then, you offset the position according to the velocity multiplied with the passed time:
sf::Vector2f velocity = getVelocityFromInput();
sf::Vector2f offset = velocity * dt.asSeconds();
sprite.move(offset);
So getVelocityFromInput() will return a constant value (say 1 or -1) on each axis?

AndrewB

  • Newbie
  • *
  • Posts: 33
    • View Profile
Re: Jittering/Shaking sprites when moving with 'forces'
« Reply #5 on: February 03, 2013, 01:13:28 am »
Nexus, I've just changed over to using the velocity*time method that you posted about and the moving sprites are still shaking.

Could it be a problem with something on my computer?

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Re: Jittering/Shaking sprites when moving with 'forces'
« Reply #6 on: February 03, 2013, 12:07:00 pm »
So getVelocityFromInput() will return a constant value (say 1 or -1) on each axis?
Yes it may return -1 if the left key is pressed, +1 if the right key is pressed, 0 if none or both are pressed.

Nexus, I've just changed over to using the velocity*time method that you posted about and the moving sprites are still shaking.
Can you post a minimal and complete example that reproduces the problem?

I'm not sure what you mean exactly with "shake", but you can try to round the position to integral coordinates.
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

AndrewB

  • Newbie
  • *
  • Posts: 33
    • View Profile
Re: Jittering/Shaking sprites when moving with 'forces'
« Reply #7 on: February 03, 2013, 12:49:03 pm »
I'll whip up something for you and see if I can record it.

Another thing, am I meant to reset dt when no key is being pressed?

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Re: Jittering/Shaking sprites when moving with 'forces'
« Reply #8 on: February 03, 2013, 12:56:38 pm »
I'll whip up something for you and see if I can record it.
In case you mean a video: That's nice, but some minimal code would also be interesting ;)

Another thing, am I meant to reset dt when no key is being pressed?
dt is always the passed frame time, independent of any input. When there is no input, the horizontal velocity may be 0, thus dt*velocity becomes 0 in x direction.
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

AndrewB

  • Newbie
  • *
  • Posts: 33
    • View Profile
Re: Jittering/Shaking sprites when moving with 'forces'
« Reply #9 on: February 03, 2013, 02:30:15 pm »
#include <SFML/Graphics.hpp>

sf::Vector2f getVelocity();

int main(int argc, char** argv)
{
    sf::RenderWindow window(sf::VideoMode(800, 600), "Movement Test");

        sf::Clock dt;

        sf::Texture tex;
        tex.loadFromFile("player.png");

        sf::Sprite player;
        player.setTexture(tex);
        player.setPosition(400.f, 300.f);

    while (window.isOpen())
    {
                dt.restart();

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

                player.move(getVelocity() * dt.getElapsedTime().asSeconds());

        window.clear(sf::Color::Black);
                window.draw(player);
        window.display();
    }

    return 0;
};

sf::Vector2f getVelocity()
{
        sf::Vector2f velocity(0.f, 0.f);
        if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
        {
                velocity.x = -1.f;
        };
        if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
        {
                velocity.x = 1.f;
        };

        return velocity;
};

Is that what you meant by using the timer for each frame? Nothing happens with that code ^

AndrewB

  • Newbie
  • *
  • Posts: 33
    • View Profile
Re: Jittering/Shaking sprites when moving with 'forces'
« Reply #10 on: February 03, 2013, 02:56:06 pm »
Pfft sorry I was distracted with something else at the time of writing that, I was meant to also show you the original method that I was using to move the player.

PS. I realise that I didn't limit the frames per second on that example and that's the reason it wasn't moving.

AndrewB

  • Newbie
  • *
  • Posts: 33
    • View Profile
Re: Jittering/Shaking sprites when moving with 'forces'
« Reply #11 on: February 04, 2013, 12:25:34 am »
#include <SFML/Graphics.hpp>

void getVelocity(sf::Vector2f&);

int main(int argc, char** argv)
{
    sf::RenderWindow window(sf::VideoMode(800, 600), "Movement Test");
        window.setFramerateLimit(60);

        sf::Texture tex;
        tex.loadFromFile("player.png");

        sf::Sprite player(tex);
        player.setPosition(400.f, 300.f);

        sf::Vector2f velocity(0.f, 0.f);

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

                getVelocity(velocity);

                // friction
                velocity.x *= 0.92;

                player.move(velocity);

        window.clear(sf::Color::Black);
                window.draw(player);
        window.display();
    }

    return 0;
};

void getVelocity(sf::Vector2f &velocity)
{
        if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
        {
                velocity.x -= 0.22f;
        };
        if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
        {
                velocity.x += 0.22f;
        };
};

This is the same method that I was originally using. The shaking is noticeable at random times if you move left/right.

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Re: Jittering/Shaking sprites when moving with 'forces'
« Reply #12 on: February 04, 2013, 06:44:36 pm »
I still don't know what you mean with "shaking", but if you refer to small irregularities in the movement, then be aware that sf::RenderWindow::setFramerateLimit() is not 100% accurate, it doesn't guarantee a FPS of 60.

By the way, for a minimal and complete code you should rather use shapes than sprites, so one can directly copy and test it...
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

AndrewB

  • Newbie
  • *
  • Posts: 33
    • View Profile
Re: Jittering/Shaking sprites when moving with 'forces'
« Reply #13 on: February 05, 2013, 12:07:51 am »
I still don't know what you mean with "shaking", but if you refer to small irregularities in the movement, then be aware that sf::RenderWindow::setFramerateLimit() is not 100% accurate, it doesn't guarantee a FPS of 60.

Hm I didn't even think about that. Would it be better if I used a sf::Clock to limit the frames myself or would it have the same effect?

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Re: Jittering/Shaking sprites when moving with 'forces'
« Reply #14 on: February 05, 2013, 01:02:47 am »
Do you mean with sf::Sleep()? That's exactly what setFramerateLimit() does ;)

There are different options to achieve what you want, one is to use dt*v and to use the processor to capacity, or a fixed time step, or simply VSync...
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development: