2D Sprite Movement

Started by
12 comments, last by leiavoia 19 years, 8 months ago
Hey everyone I've been working on a 2D engine for a little while now, and I've got my sprite engine working in pretty full force. Playing around with moving my sprites across the screen, I realized an inherit problem in sprite movement that I can't figure out how to get past. My resolution is 640x480, and if I were to move my sprite right 1 or 2 pixels per frame, the movement is way to slow for most games. But when I move it, say 5 pixels per second, the movement is extremely choppy. This suggests to me that the only way to get fast movement without choppiness is to use a really low resolution. What am I missing? Am I overestimating the resolution of the 2D games I'm used to, or is it something else? Thanks for any helpful discussion.
__________________________We're all Dumb And Jaded
Advertisement
You can smooth things out using interpolation, if your main loop is structured correctly. Modern vid-cards usually have enough oomph to drive framerates far beyond your game's update speed. For instance, if your game is updating at, say, 25 FPS and your card can drive it at 100 FPS, then the same frame is being drawn over and over for 4 frames before anything changes. During an update, if your character moves, say, 4 pixels, then you get a visual jump of 4 pixels, which can look bad. But if you structure things so that those inbetween frames are used by way of interpolation, then instead of jumping 4 pixels, the character will move by 1 pixel spread out across the 4 video frames that are drawn between updates. It's a little confusing, and I probably didn't word it very well, but you can take a look at this article on my website, which gives an overview of a loop structure first detailed by Javier Arevalo as a Flipcode tip of the day. It describes how you can store an object's Last and Next positions, calculate an interpolation factor (t) based on how far into the next frame you are, and use that factor to draw the object at intermediate positions between Last and Next, so that the object will smoothly move from one position to the next without the jarring, abrupt jump.

Edit: Oh, yeah, and you're probably not overestimating resolutions. 640x480 is pretty low res, especially for a 2D game which usually renders faster than 3D games.

Also, there is a very simple SDL sample program linked from the above article that you can use to see for yourself the effect that interpolation can have on your visual smoothness.
Another solution is just to use time independent movement...then if your FPS is high your sprites will move smooth as silk. Just calculate a delta time for each frame and multiply each movement value by that.
time independent movement also has the benefit of running at the same speed on different systems.
--- krez ([email="krez_AT_optonline_DOT_net"]krez_AT_optonline_DOT_net[/email])
Quote:Original post by krez
time independent movement also has the benefit of running at the same speed on different systems.


So does fixed timestep movement.
You need to work with sub-pixel accurate movement. That was the key for me. See, if you round off to the nearest pixel on each frame, you'll get really hurky-jerky movement, either too fast or too slow or some of each off and on (BIG STEP small step BIG STEP small step, like that).

How you do that is simply change your character's X/Y coords from ints to floats. Such a simple thing, but makes a big difference (at least for me)

Of course when you go to actually draw the thing, you round it to the nearest pixel, but you keep the actual position data in floats so that you don't lose little bits here and there.

That also implies that your movement is in "Pixels Per Second" and not just "Pixels"
I've seen the same problem many times and usually the 2 common factors are:

- Using integers for pixels movement. Such as moving 4 pixels per frame.
- Using frame dependent movement, instead of time dependent movement.

The chopiness is caused when your sprite jumps from its last position to another one without a smoot movement. When you move it 4 pixels, you're telling it to jump 4 pixels between a frame and the next, rather than moving it slowly.

Also, take in account that frames don't last the same time. Some frames last longer than others, depending on what needs to be processed. If you use frame dependent movement, then your sprite is not moving smoothly. To do that, you must use floats instead of integers, and base the movement in time. That way, even when a frame is shorter than other, you don't mind, as the movement will be updated based on the time, and it will take that into account.
So your sprite will move more in long frames, and less in short ones, giving a constant pixels/sec speed, that is, a smooth movement.
-----DevZing Blog (in Spanish)
To solve this problem I always use time independent movement. Basically that scales the movement of your objects based on the amount of time it took your system to complete a game cycle. So you'd calculate time each time through your main loop, and end up with a "last time" (oldTIme - newTime) variable (of type float!) and pass it to your update function.

Your update function might look something like...
void Update(float timeScale){    velocity.x = speed;    velocity.y = speed;    x += velocity.x*timeScale;    y += velocity.y*timeScale;}



Of course you would adjust your velocity with some key input, making the vector move in what direction you'd want it to...
"Creativity requires you to murder your children." - Chris Crawford
Quote:Original post by leiavoia
Of course when you go to actually draw the thing, you round it to the nearest pixel, but you keep the actual position data in floats so that you don't lose little bits here and there.

That also implies that your movement is in "Pixels Per Second" and not just "Pixels"


Alright, thanks everyone for the input. I haven't tried impementing any of this yet, so before I go on I'd like to say I'm not doubting any of your solutions, in fact I'm sure they will work. But still, conceptually there's something bugging me that I can't shake.

Say I want my sprite moving as fast as it would move if I would use my old method of incrementing by 4 frames per second. Of course in my old method, this will result in jerkiness.

Yet, if I were to use time based movement or even change my coordinates to floats and go the sub-pixel route, none of these can change the unescapable fact that my character can only change position once every frame. So even if I'm working at 60 fps (which I was using), despite what I do under the hood with floating points or timestep movement, he's still got to move 4 pixels every frame to keep up that speed (at least in my head).

So to sum it up, I can't show his movement pixel by pixel because the framerate isn't fast enough to show it in that small of an increment, yet I can't show it by more than that because it's to large of an increment to be rendered smoothly.

Again, I realize I'm just having a conceptual problem with this and your suggestions will fix things, but I'd just really like to get past this mental hurdle that I can't get through.
__________________________We're all Dumb And Jaded
4 pixels per second won't be choppy unless your actual framerate is low. If you're running at 60fps then it'll look smooth as silk.

However you really *don't* want to use time based movement for a 2d game. While its great for 3d it tends to look terrible in 2d where minor glitches and hiccups can cause the movement to look irregular. This might even be the cause of your problems, perhaps your movement or your framerate isn't contantly hitting the 60fps mark?

This topic is closed to new replies.

Advertisement