I created a game using Swing, and it was a bit unreliable, so I started remaking it using Slick2D game engine and I have encountered issues.
The background of the game rolls across the screen at a certain about of pixels each time the update method is called. This keeps speeding up and slowing down, so the background will move very fast, and then very slow, and keeps fluctuating.
I have tried * by delta (which monitors the refresh rate, I think!) on my value which moves the background, but as this wont give me an exact value I can use to reset the background to the left hand side (2 background move from right to left. left hand one goes to the right at -800 pixels).
What is causing this and how do I overcome it?
Thanks
Here's some reading for you (there's a gamedev-specific StackExchange site, BTW):
- https://gamedev.stackexchange.com/questions/6825/time-based-movement-vs-frame-rate-based-movement
- https://gamedev.stackexchange.com/questions/1589/fixed-time-step-vs-variable-time-step
One of the most important points in these articles is that things move at a certain rate OVER TIME, not over a certain number of frames. Since frame rates can unpredictably change, time-based and frame-based movement don't wind up being equivalent to one another.
And here's some explanation...
So, your computer and OS are multithreaded, and thus, you can never know what's happening outside your app, and what the overall load is on the machine. Because of this, even when you're in full-screen mode you aren't getting exclusive access to the CPU. So, that's one factor to why things speed up and slow down.
The delta's purpose in Slick2D is to allow you to deal with this speed up/slow down, and allow your app to change its frame rate dynamically so that the perceived movement on the screen doesn't change due to the load on your machine. The delta is not the monitor the refresh rate (which is constant); the delta is the number of milliseconds that have passed since the last call to update
.
So how do you use this delta properly? Let's say your background is supposed to move at a rate of 100px/sec. If the delta (on a given call to update
) is 33 milliseconds, then the amount you should move your background on this update is 100*(33/1000.0) = 0.033
- so you would move your background by 0.033 pixels. This might seem weird, and you may wonder what the point is of moving <1 pixel, but stick with me.
First, the reason you have to divide it by 1000.0 instead of 1000, is because you want the movement of the delta to give you a floating point number.
You'll notice that the 2D graphics stuff in Slick2D uses float values to track the placement of things. That's because if the delta tells you to move something by 0.033 pixels, you need to move it by 0.033: not 0, and not 1 pixels. Sub-pixel movement is critical to smoothing out the increase/decrease in frame rates as well, because the cumulative effect over several sub-pixel movements is that, when the moment is right, all those little movements add up to a whole pixel, and it's perfectly smooth, resulting in the correct overall movement rate.
You may think that, since your screen resolves images to a given pixel, and not sub-pixel elements, that it doesn't matter if you do sub-pixel movement, but if you convert all your movement tracking to floats, you'll see that the effect you're observing largely goes away.