In the Variable timestep
game loop, we take a measure of how long the loop is taking to execute, and use that to compute a "delta" that will be applied to the animations. If the loop executes quickly (higher fps) then the delta will be smaller, causing the movement to be less per frame
. If the execution speed slows down for a loop, the delta will be larger, and the movement on that iteration of the game loop will be greater.
In this scenario, OPTIMAL_TIME is being used as a denominator for the calculation of the delta. The exact value of the OPTIMAL_TIME looks to me to be somewhat arbitrary. I assume Eli set it to this value because he wanted to be sure that it was never less than the elapsed nanoseconds for a given loop. Whatever the value is set to be, and whatever deltas result from the calculation, the animations will have to be "tuned" to work correctly with those deltas.
Just in case you've missed the point about how the deltas are used: lets say you have a target speed for an animation of 2 pixels per frame, e.g., xVel = 2
. Thus, the animation computation is: xPos += xVel;
With variable timestep game loops, we would multiply xVel by delta before
adding it to xPos. Since the delta is a function of the elapsed time, when more time elapses, the delta is larger, when the loop processes more quickly the delta is smaller. The OPTIMAL_TIME denominator helps 'tune' the delta to a value that makes sense for the animation computation. We want deltas to mess with the xVel a "reasonable" amount. I'm not sure what reasonable is here, maybe 50% to 200%? I'm guessing in your attempts to use the delta, the value when multiplied against xVel or yVel produced some unreasonable movement values because it wasn't tuned very well.
A "simpler" game loop can mean different things. If you want to eliminate the fractional aspect of the animations (it seems like you already do this, since you eliminated the delta, according to your post), but ensure that the game runs the same speed on various computers and runs the same speed when vastly different amounts of computations are made per loop, then a common strategy is to use a variable amount of sleep per loop in order to ensure each loop takes the same amount of time.
Thus, we save the time at the top of the loop, and as the last set of commands for the loop, inspect the elapsed time and sleep the difference between the elapsed time and the fixed target time for the loop. The following code illustrates the basic concept.
long startTime = System.nanoTime();
long elapsedTime = System.nanoTime() - startTime;
Problems with this:
(a) accuracy of the system clock. With Microsoft OS's, I think the system clock is often set to update every 15.5 millis or something like that. Lots of folks here talk about getting around this by kicking the system clock into a higher gear, but I can't recall the exact method. I think it was running a concurrent
Thread with a sleep command with a very high value: e.g., Thread.sleep(Long.MAX_VALUE);
(b) the game loop speed is only capped, not prevented from slow downs. If your game loop code takes so long to execute that it creates an elapsedTime value that is larger than the TARGET_TIME, there is no provision for "catching up".
NOTE: this is EXACTLY THE SAME COMPLAINT used against the util.Timer in Eli's tutorial!! (And, the same performance result.) Thus, this simpler game loop method is in effect pretty much equivalent to using the util.Timer (NOT the swing.Timer).
I do not share the prejudice held here by many at JGO against the use of util.Timer for game loops. Most here prefer to use some variant of the variable-sleep amount. But, we could schedule a fixed-time loop with a simple timer-scheduling command, e.g., from Eli's:
timer.schedule(new GameLoop(), 0, 1000 / 60.0);
NOTE: I changed his LoopyStuff() to GameLoop() [purely cosmetic] but also, made the repeat interval a double rather than an integer calculation! [tutorial bug fix]
With this, the GameLoop object is an extension of TimerTask, as Eli presents. There's no need to calculate elapsed times or manage sleep intervals.