4
\$\begingroup\$

I am trying to figure out if there is a way to move a sprite smoothly on the screen at different speeds without stuttering, but keeping the effect that it's moving smoothly; especially at faster velocities.

Below is a basic version of what I have with all of the object specific logic stripped out for readability.

void MoveableGameObject::update(double time)
{
    //maxVelocity is 10
    currentVelocity = min<float>(currentVelocity + acceleration * time, maxVelocity);
    location.x += currentVelocity;
}

void MoveableGameObject::draw()
{
    sprite->draw(location.x, location.y)
}

The part that I do not like is that the next time the frame renders and max velocity has been achieved, the sprite jumps 10 pixels and looks stuttery. If I tone down the numbers then it is of course smoother, but also slower.

I need to find a way to still have the speed, but give a smooth transition somehow. I am having a hard time wrapping my head around trying to implement movement speeds. Am I just using the wrong scale in terms of velocity to pixels?

My brain hurts, but I am still having a blast tinkering around with this and is a nice change of pace from doing nothing but business applications for the past 7 years.

I do have the ability to say run the game logic 20 times a second while rendering at 60 frames a second. Figured I would mention that in case that helps with an answer. Currently they are both just set to 60 since I am only running a single sprite and wanted to test the movement and check the sprite location on update() vs. draw().

Thanks in advance for any help.

EDIT: I forgot to mention and not sure if it matters or not, but I am currently using SDL to render.

\$\endgroup\$
2
  • 2
    \$\begingroup\$ It could be a vertical sync problem? The choppy-ness could be from the fact how your buffer is rendered at the refresh rate. \$\endgroup\$
    – Sidar
    Commented Feb 10, 2013 at 4:28
  • \$\begingroup\$ @Sidar It's not that. I have the frame rate capped at 60FPS. I double checked and am only rendering 60 times a second. The stuttering that I am talking about is just the fact that the sprite is moving 10 pixels at a time and I want to know if there is a way to have smooth transitions. Am I supposed to doing everything time based? For instance -- it takes x seconds to move y pixels and then figure out a calculation on how many pixels to move based on the time I started moving? \$\endgroup\$
    – TyCobb
    Commented Feb 10, 2013 at 4:43

3 Answers 3

1
\$\begingroup\$

Is that update(time) or update(dt)?

You would have something like:

void frameUpdate(){
   dt = time - oldTime;
   time = oldTime;

   // FPS at that specific frame would be 1.0/dt assuming time is in seconds
   // Normally you get the time in microseconds or at least milliseconds
   //   so it would be 1.0/(dt*1e6) or 1.0/(dt*1e4)

   update(dt);
}
\$\endgroup\$
4
\$\begingroup\$

You should probably change the line:

location.x += currentVelocity;

to

location.x += currentVelocity * time;

Remember that velocity describes the change in position per time.

In fact, for added accuracy, you could rewrite your update() method to look like this:

void MoveableGameObject::update(double time)
{
    double oldVelocity = currentVelocity;
    currentVelocity = min<float>(oldVelocity + acceleration * time, maxVelocity);
    location.x += time * (oldVelocity + currentVelocity) / 2;
}

The averaging of oldVelocity and currentVelocity accounts for the fact that the velocity is actually changing during the timestep due to acceleration, so (assuming constant acceleration) the average velocity is halfway between them.

For constant acceleration, ignoring the maximum velocity cap, this formula will, in fact, give exact results regardless of the timestep. (It amounts to the same thing as the Δx = v·Δt + ½a·Δt2 formula you may recall from high school physics for motion under constant acceleration.) If the acceleration varies, you can get even more accurate results using (e.g.) the velocity Verlet method.

\$\endgroup\$
1
\$\begingroup\$

It seems that your acc and vel integration isn't right. I'm too busy to write a full answer right now, but read this link: http://lol.zoy.org/blog/2011/12/14/understanding-motion-in-games and also see this ANIMATED presentation on the matter too: http://richardlord.net/presentations/physics-for-flash-games

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .