1
Graphics / Completely Eliminating Jittery Movement
« on: October 21, 2013, 09:16:22 pm »
First, before getting started, I'd like to define what I mean by jittery movement — every 500 ticks or so, the sprite being moved might jerk forward a little bit, and then snap back in place, thus appearing to be jittery/stuttering while moving.
The stuttering is a lot more apparent if I force hard vertical synchronization or specify a capped frame rate limit using the SFML API, which I assume is because I've already implemented a fixed timestep and interpolation that might not work well with these limits.
The stuttering is hardly noticeable for me, but it's a lot more apparent for my friends with lower-end hardware, so I think I'm just doing things inefficiently. Currently, I've turned off everything except for x movement for the player class to make the scope of the problem easier to manage.
Game Loop:
Player.cpp:
I'd appreciate any help to see if I'm doing things inefficiently, or what else might be causing the occasional stuttering.
The stuttering is a lot more apparent if I force hard vertical synchronization or specify a capped frame rate limit using the SFML API, which I assume is because I've already implemented a fixed timestep and interpolation that might not work well with these limits.
The stuttering is hardly noticeable for me, but it's a lot more apparent for my friends with lower-end hardware, so I think I'm just doing things inefficiently. Currently, I've turned off everything except for x movement for the player class to make the scope of the problem easier to manage.
Game Loop:
void Application::initialize()
{
videoMode.width = 1067;
videoMode.height = 600;
videoMode.bitsPerPixel = 32;
dt = 1.0f / 60.0f;
timeNow = gameClock.getElapsedTime().asSeconds();
timeFrame = 0.0f;
timeActual = 0.0f;
accumulator = 0.0f;
enableVSync = false;
doForceFPS = false;
forceFPS = 60;
}
int Application::run(int argc, char **argv)
{
...
pushWorld(new TownlevelWorld());
while (rwin.isOpen())
{
sf::Event event;
while (rwin.pollEvent(event))
{
cont_worlds.top()->input(event);
...
}
timeNow = gameClock.getElapsedTime().asSeconds();
timeFrame = timeNow - timeActual;
if (timeFrame > 0.25f)
timeFrame = 0.25f;
timeActual = timeNow;
accumulator += timeFrame;
while (accumulator >= dt)
{
cont_worlds.top()->update(dt);
accumulator -= dt;
}
const float interpolation = accumulator / dt;
rwin.clear();
cont_worlds.top()->draw(rwin, interpolation);
rwin.display();
}
release();
return 0;
}
{
videoMode.width = 1067;
videoMode.height = 600;
videoMode.bitsPerPixel = 32;
dt = 1.0f / 60.0f;
timeNow = gameClock.getElapsedTime().asSeconds();
timeFrame = 0.0f;
timeActual = 0.0f;
accumulator = 0.0f;
enableVSync = false;
doForceFPS = false;
forceFPS = 60;
}
int Application::run(int argc, char **argv)
{
...
pushWorld(new TownlevelWorld());
while (rwin.isOpen())
{
sf::Event event;
while (rwin.pollEvent(event))
{
cont_worlds.top()->input(event);
...
}
timeNow = gameClock.getElapsedTime().asSeconds();
timeFrame = timeNow - timeActual;
if (timeFrame > 0.25f)
timeFrame = 0.25f;
timeActual = timeNow;
accumulator += timeFrame;
while (accumulator >= dt)
{
cont_worlds.top()->update(dt);
accumulator -= dt;
}
const float interpolation = accumulator / dt;
rwin.clear();
cont_worlds.top()->draw(rwin, interpolation);
rwin.display();
}
release();
return 0;
}
Player.cpp:
void Player::draw(sf::RenderWindow &rwin, float interp)
{
rwin.draw(self);
sf::Vector2f posInterp = pos;
if (pos.x != lastPos.x)
posInterp.x += interp;
if (pos.y != lastPos.y)
posInterp.y += interp;
self.setPosition(posInterp.x, posInterp.y);
lastPos = pos;
}
void Player::update(float dt)
{
if (right == true && left == false)
{
xs += speed;
}
if (right == false && left == true)
{
xs -= speed;
}
if (!sf::Keyboard::isKeyPressed(sf::Keyboard::Right) && !sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
{
right = false;
left = false;
}
pos.x += clamp(xs, -6, 6);
xs /= fric;
}
{
rwin.draw(self);
sf::Vector2f posInterp = pos;
if (pos.x != lastPos.x)
posInterp.x += interp;
if (pos.y != lastPos.y)
posInterp.y += interp;
self.setPosition(posInterp.x, posInterp.y);
lastPos = pos;
}
void Player::update(float dt)
{
if (right == true && left == false)
{
xs += speed;
}
if (right == false && left == true)
{
xs -= speed;
}
if (!sf::Keyboard::isKeyPressed(sf::Keyboard::Right) && !sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
{
right = false;
left = false;
}
pos.x += clamp(xs, -6, 6);
xs /= fric;
}
I'd appreciate any help to see if I'm doing things inefficiently, or what else might be causing the occasional stuttering.