If you need
fixed precision, stick to integers and longs

FTFY. Just don't EVER use a delta time step with integers. That's literally suicide. xD
Delta time steps have done funny things in big commercial games like Call of Duty. At some specific FPS points (125, 250 and 333) your jump height increases markedly allowing you to get outside the map or to places you aren't supposed to be able to get to.
http://www.youtube.com/v/OUgcnBMJ9-s?version=3&hl=en_US&start=What you want is pretty much fixed step logic combined with rendering at a very high speed. Therefore it's a good idea to set the update rate low enough to make sure that the game doesn't slow down on older computers, but fast enough to not introduce noticeable delay (usually manifested as "input delay" since that's what players actually notice). A good idea is to do 30 updates per second. It's possible to keep your current threaded design, but I don't think it's worth the additional complexity.
You also want rendering to be decoupled from updating. We'd rather run the game at 15 FPS than reduce the game speed in an extremely heavy scene, so we need to make sure that we can do multiple updates per rendered frame. This is easy to implement of course, just render when we have time over.
However, we also want the game to be able to run faster than 30 FPS, so we will need to use interpolation for our rendering to get smooth movement for objects at 60 FPS or any other FPS than 30. A game that did not include such interpolation was Command & Conquer Generals, so the game's FPS is locked to the update rate, which in turn depends on the game speed setting. Not a very good design in other words.
I'd recommend this article which gives a good overview of good and bad game loops:
http://www.koonsolo.com/news/dewitters-gameloop/. It's not Java but it should be easy to understand, although the variable names are a bit weird. Dammit, now I feel like I have to port it!

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| private final int UPDATES_PER_SECOND = 30; private final long NANOS_PER_UPDATE = 1000000000L / UPDATES_PER_SECOND;
private final int MAX_FRAMESKIP = 5;
...
long nextUpdate = System.nanoTime(); long lastUpdate = nextUpdate;
while(running){ int updates = 0; while(nextUpdate > System.nanoTime() && updates < MAX_FRAMESKIP){ update(); lastUpdate = nextUpdate; nextUpdate += NANOS_PER_UPDATE; updates++; } float interpolationAlpha = Math.min((float)(System.nanoTime() - lastUpdate) / NANOS_PER_UPDATE, 1); renderWithInterpolation(interpolationAlpha); } |
The article actually does EXTRApolation, not interpolation. It's trying to predict where objects are moving. Instead, I would
interpolate between the last state and the current state, at the cost of having a small (input) delay instead of trying to predict the future causing objects to continue into each other before being corrected when the next frame detects their collision. In short, each object needs to know its position last frame and its current position, and you linearly interpolate between those two based on an interpolation alpha value like this:
float interpolatedX = lastX * (1 - alpha) + currentX * alpha; |