Game loops!

There are a lot of different sorts of game loops you can use. In general, you can think of a game loop as having 3 different pieces:

  1. Some sort of, well… loop. From timer calls to while loops to recursive function calls. (the loop)
  2. A way to delay the length of each loop iteration so you get a frame rate you like. (the timing mechanism)
  3. A way to make the game speed remain independent of the speed of the loop. (the interpolation)

Bad Loops
Let’s start with some pretty ugly ones I’ve seen that you definitely shouldn’t do:


public void gameLoop()
{
    while(true) //the loop
    {
        doGameUpdates();
        render();
        for (int i = 0; i < 1000000; i++) ; //the timing mechanism
    }
}

OMG so bad. Don’t ever do that. I’ve literally seen it in people’s games though. Aside from maxing out your processor, that’s going to be a completely varying length of time for each machine and even might have variation on your machine. Bad bad bad. You can also see that this is missing a method of interpolation, but there’s no way to provide that when it doesn’t measure time in any way!


public void gameLoop()
{
    while(true) //the loop
    {
        doGameUpdates();
        render();
        Thread.sleep(1); //the timing mechanism
    }
}

This is better, but still not great. Thread.sleep is not always going to be accurate, plus if you’ve got any other threads hogging processor it won’t necessarily allow your thread to resume in time. From the java docs:

Also, this is missing interpolation. That’s because this sort of loop assumes that Thread.sleep() is actually going to be 100% accurate, but we know it isn’t.

Another issue that we see with both of these loops is the self-defined infinite loop that is “while(true).” We know that this loop can never ever end. It’s impossible. I will absolutely advise against doing this, ever. It will only cause problems. Even though, conceptually, we don’t want this loop ever to end, it’s a good idea to pop a boolean in there so you at least have the option if killing the loop.


private boolean isRunning;

public void gameLoop()
{
    while(isRunning) //the loop
    {
        doGameUpdates();
        render();
        Thread.sleep(1); //the timing mechanism
    }
}

Great, now we can set isRunning to false whenever we want to stop the game loop, or pause the game, or anything like that.

Here’s a crazy recursive way of doing the same loop:


private boolean isRunning;

public void gameLoop()
{
    doGameUpdates();
    render();
    Thread.sleep(1); //the timing mechanism
    if (isRunning)
    {
        gameLoop(); //the loop
    }
}

I don’t know why’d you ever do that, but it’s another thing I’ve seen so I’ve included it for completion’s sake. Aside from being not obvious, I think this will eventually cause a stack overflow (someone correct me if I’m wrong).

Decent loops, but I still wouldn’t use them
I think I’ve seen the approach of using either java.util.Timer or javax.swing.Timer more often than any other approach (at least in amateur projects). This is nice because it saves you from having to deal with any part of the loop yourself, and it’s more or less accurate. The reason for this is that neither of the two Timer classes are intended to be used as heavy-lifting tasks. java.util.Timer specifically says “Timer tasks should complete quickly. If a timer task takes excessive time to complete, it “hogs” the timer’s task execution thread” in the Java docs. Even better, javax.swing.Timer is meant to be used with Swing (go figure), so it is not at all a reliable timing solution. It fires all events on the EDT (event-dispatching-thread), which is used for all Swing events. So, your action might be fired after a lot of other things, thereby resulting in a very unpredictable timing solution.

Still, avoiding the overhead of dealing with your own timing system can be nice.

java.util.Timer:


private java.util.Timer timer;
private boolean isRunning;

public void gameLoop()
{
    timer = new Timer();
    timer.schedule(new LoopyStuff(), 0, 1000 / 60); //new timer at 60 fps, the timing mechanism
}

private class LoopyStuff extends java.util.TimerTask
{
    public void run() //this becomes the loop
    {
        doGameUpdates();
        render();

        if (!isRunning)
        {
            timer.cancel();
        }
    }
}

I won’t bother laying out javax.swing.Timer, because it is totally suck. Don’t use it!

Good game loops
So, in all those examples, we’ve got issues with the reliability of timers. If your game logic is only updating at 30 times per second, how do you draw anything at 60 fps? Similarly, if your fps is down to 10, how do you keep the updates at 30? Or, if your game is updating at 70 times per second one frame and 10 times per second another frame, how do you ensure that the game speed is consistent for players?

Remember that third component of a game loop that we haven’t used yet? That’s right, we need to use interpolation.

In terms of your loop, you have two options:

  • Variable timestep
  • Fixed timestep

Which one you use depends on personal preference and also what sort of things you are doing in your loops.

Variable timestep loops are great because the game will seem consistent regardless of how fast the player’s computer is. allowing you to potentially cater to lots of different types of machines. They also often allow you to update the game logic with very high granularity, that can make a much better experience in certain games. Things are drawn as they change position, so there is no graphical latency whatsoever.

Fixed timestep loops are great because you know that every single timestep will take up the exact same length of time. This means you will always have consistent gameplay, regardless of how fast a machine is. This works wonderfully for math-heavy games, like physics operations, and is also my loop of choice for networked games so that you know packets are going and coming at a generally constant speed. You also can keep the game logic running at a very low rate while the frame rate can still get extremely high, albeit with one frame of latency.

You can’t really use variable timestep well in physics simulations, and fixed timestep fails in situations where your game can be interrupted or on machines that are too slow to hit your fixed rate.

Here’s where the interpolation comes in:

  • If you are using a variable stepped loop, then you need to update the game different amounts depending on how long recent updates took. You will use a delta value to do this, which you multiply times every single value that updates based on time (think of things like velocity, position, attack rate, and the like). A delta of 1.0 means that your loop took as long as you normally expect (an “optimal” amount of time), where as a delta of < 1 means that the loop is going faster than optimal, and a delta of > 1 means that it’s slower.
  • If you are using a fixed timestep, then you have three options: you can either have a very high fixed update (which lowers the number of machines that can reliably run your game), you can have a very low frame rate (if the positions of your characters are only updating 20 times per second, then no matter how fast the rendering is going it’s only going to render those 20 frames), or you can interpolate the most recent update to the current one over each render. That sounds confusing, but it’s not hard to implement, and it gives you yummy butter smoothness!

Both obviously have some caveats you’re going to need to worry about. With the former, you need to multiply every single time-based updated values by the delta. This is a pain in the butt and it’s pretty easy to forget to multiply by the delta sometimes, but it’s reliable and it works. In the latter, you’ve got to multiply all time-based rendered values by the interpolation amount. Also a pain in the butt!

Personally, I usually use a fixed timestep loop, because it’s generally less to think about. My logic is almost always much more complicated than my rendering, and you can usually abstract out the interpolation so that you don’t have to worry about it more than once. However, I’d use whatever makes sense to you!

Without further ado, here are implementations:
Variable timestep (credit goes to Kevin Glass on his site, with heavy changes)


public void gameLoop()
{
	long lastLoopTime = System.nanoTime();
	final int TARGET_FPS = 60;
	final long OPTIMAL_TIME = 1000000000 / TARGET_FPS;	

	// keep looping round til the game ends
	while (gameRunning)
	{
		// work out how long its been since the last update, this
		// will be used to calculate how far the entities should
		// move this loop
		long now = System.nanoTime();
		long updateLength = now - lastLoopTime;
		lastLoopTime = now;
		double delta = updateLength / ((double)OPTIMAL_TIME);

		// update the frame counter
		lastFpsTime += updateLength;
		fps++;
		
		// update our FPS counter if a second has passed since
		// we last recorded
		if (lastFpsTime >= 1000000000)
		{
			System.out.println("(FPS: "+fps+")");
			lastFpsTime = 0;
			fps = 0;
		}
		
		// update the game logic
		doGameUpdates(delta);
		
		// draw everyting
		render();
		
		// we want each frame to take 10 milliseconds, to do this
		// we've recorded when we started the frame. We add 10 milliseconds
		// to this and then factor in the current time to give 
		// us our final value to wait for
		// remember this is in ms, whereas our lastLoopTime etc. vars are in ns.
		try{Thread.sleep( (lastLoopTime-System.nanoTime() + OPTIMAL_TIME)/1000000 )};
	}
}

private void doGameUpdates(double delta)
{
	for (int i = 0; i < stuff.size(); i++)
	{
		// all time-related values must be multiplied by delta!
		Stuff s = stuff.get(i);
		s.velocity += Gravity.VELOCITY * delta;
		s.position += s.velocity * delta;
		
		// stuff that isn't time-related doesn't care about delta...
		if (s.velocity >= 1000)
		{
			s.color = Color.RED;
		}
		else
		{
			s.color = Color.BLUE;
		}
	}
}


Fixed timestep (credit goes to me, this includes an example with a ball bouncing around so that you can clearly see how interpolation works)


import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class GameLoopTest extends JFrame implements ActionListener
{
   private GamePanel gamePanel = new GamePanel();
   private JButton startButton = new JButton("Start");
   private JButton quitButton = new JButton("Quit");
   private JButton pauseButton = new JButton("Pause");
   private boolean running = false;
   private boolean paused = false;
   private int fps = 60;
   private int frameCount = 0;
   
   public GameLoopTest()
   {
      super("Fixed Timestep Game Loop Test");
      Container cp = getContentPane();
      cp.setLayout(new BorderLayout());
      JPanel p = new JPanel();
      p.setLayout(new GridLayout(1,2));
      p.add(startButton);
      p.add(pauseButton);
      p.add(quitButton);
      cp.add(gamePanel, BorderLayout.CENTER);
      cp.add(p, BorderLayout.SOUTH);
      setSize(500, 500);
      
      startButton.addActionListener(this);
      quitButton.addActionListener(this);
      pauseButton.addActionListener(this);
   }
   
   public static void main(String[] args)
   {
      GameLoopTest glt = new GameLoopTest();
      glt.setVisible(true);
   }
   
   public void actionPerformed(ActionEvent e)
   {
      Object s = e.getSource();
      if (s == startButton)
      {
         running = !running;
         if (running)
         {
            startButton.setText("Stop");
            runGameLoop();
         }
         else
         {
            startButton.setText("Start");
         }
      }
      else if (s == pauseButton)
      {
	     paused = !paused;
         if (paused)
         {
            pauseButton.setText("Unpause");
         }
         else
         {
            pauseButton.setText("Pause");
         }
      }
      else if (s == quitButton)
      {
         System.exit(0);
      }
   }
   
   //Starts a new thread and runs the game loop in it.
   public void runGameLoop()
   {
      Thread loop = new Thread()
      {
         public void run()
         {
            gameLoop();
         }
      };
      loop.start();
   }
   
   //Only run this in another Thread!
   private void gameLoop()
   {
      //This value would probably be stored elsewhere.
      final double GAME_HERTZ = 30.0;
      //Calculate how many ns each frame should take for our target game hertz.
      final double TIME_BETWEEN_UPDATES = 1000000000 / GAME_HERTZ;
      //At the very most we will update the game this many times before a new render.
      //If you're worried about visual hitches more than perfect timing, set this to 1.
      final int MAX_UPDATES_BEFORE_RENDER = 5;
      //We will need the last update time.
      double lastUpdateTime = System.nanoTime();
      //Store the last time we rendered.
      double lastRenderTime = System.nanoTime();
      
      //If we are able to get as high as this FPS, don't render again.
      final double TARGET_FPS = 60;
      final double TARGET_TIME_BETWEEN_RENDERS = 1000000000 / TARGET_FPS;
      
      //Simple way of finding FPS.
      int lastSecondTime = (int) (lastUpdateTime / 1000000000);
      
      while (running)
      {
         double now = System.nanoTime();
         int updateCount = 0;
         
         if (!paused)
         {
         	 //Do as many game updates as we need to, potentially playing catchup.
	         while( now - lastUpdateTime > TIME_BETWEEN_UPDATES && updateCount < MAX_UPDATES_BEFORE_RENDER )
	         {
	            updateGame();
	            lastUpdateTime += TIME_BETWEEN_UPDATES;
	            updateCount++;
	         }
	
	         //If for some reason an update takes forever, we don't want to do an insane number of catchups.
	         //If you were doing some sort of game that needed to keep EXACT time, you would get rid of this.
	         if ( now - lastUpdateTime > TIME_BETWEEN_UPDATES)
	         {
	            lastUpdateTime = now - TIME_BETWEEN_UPDATES;
	         }
         
	         //Render. To do so, we need to calculate interpolation for a smooth render.
	         float interpolation = Math.min(1.0f, (float) ((now - lastUpdateTime) / TIME_BETWEEN_UPDATES) );
	         drawGame(interpolation);
	         lastRenderTime = now;
         
	         //Update the frames we got.
	         int thisSecond = (int) (lastUpdateTime / 1000000000);
	         if (thisSecond > lastSecondTime)
	         {
	            System.out.println("NEW SECOND " + thisSecond + " " + frameCount);
	            fps = frameCount;
	            frameCount = 0;
	            lastSecondTime = thisSecond;
	         }
         
	         //Yield until it has been at least the target time between renders. This saves the CPU from hogging.
	         while ( now - lastRenderTime < TARGET_TIME_BETWEEN_RENDERS && now - lastUpdateTime < TIME_BETWEEN_UPDATES)
	         {
	            Thread.yield();
            
	            //This stops the app from consuming all your CPU. It makes this slightly less accurate, but is worth it.
	            //You can remove this line and it will still work (better), your CPU just climbs on certain OSes.
	            //FYI on some OS's this can cause pretty bad stuttering. Scroll down and have a look at different peoples' solutions to this.
	            try {Thread.sleep(1);} catch(Exception e) {} 
            
	            now = System.nanoTime();
	         }
	      }
      }
   }
   
   private void updateGame()
   {
      gamePanel.update();
   }
   
   private void drawGame(float interpolation)
   {
      gamePanel.setInterpolation(interpolation);
      gamePanel.repaint();
   }
   
   private class GamePanel extends JPanel
   {
      float interpolation;
      float ballX, ballY, lastBallX, lastBallY;
      int ballWidth, ballHeight;
      float ballXVel, ballYVel;
      float ballSpeed;
      
      int lastDrawX, lastDrawY;
      
      public GamePanel()
      {
         ballX = lastBallX = 100;
         ballY = lastBallY = 100;
         ballWidth = 25;
         ballHeight = 25;
         ballSpeed = 25;
         ballXVel = (float) Math.random() * ballSpeed*2 - ballSpeed;
         ballYVel = (float) Math.random() * ballSpeed*2 - ballSpeed;
      }
      
      public void setInterpolation(float interp)
      {
         interpolation = interp;
      }
      
      public void update()
      {
         lastBallX = ballX;
         lastBallY = ballY;
         
         ballX += ballXVel;
         ballY += ballYVel;
         
         if (ballX + ballWidth/2 >= getWidth())
         {
            ballXVel *= -1;
            ballX = getWidth() - ballWidth/2;
            ballYVel = (float) Math.random() * ballSpeed*2 - ballSpeed;
         }
         else if (ballX - ballWidth/2 <= 0)
         {
            ballXVel *= -1;
            ballX = ballWidth/2;
         }
         
         if (ballY + ballHeight/2 >= getHeight())
         {
            ballYVel *= -1;
            ballY = getHeight() - ballHeight/2;
            ballXVel = (float) Math.random() * ballSpeed*2 - ballSpeed;
         }
         else if (ballY - ballHeight/2 <= 0)
         {
            ballYVel *= -1;
            ballY = ballHeight/2;
         }
      }
      
      public void paintComponent(Graphics g)
      {
         //BS way of clearing out the old rectangle to save CPU.
         g.setColor(getBackground());
         g.fillRect(lastDrawX-1, lastDrawY-1, ballWidth+2, ballHeight+2);
         g.fillRect(5, 0, 75, 30);
         
         g.setColor(Color.RED);
         int drawX = (int) ((ballX - lastBallX) * interpolation + lastBallX - ballWidth/2);
         int drawY = (int) ((ballY - lastBallY) * interpolation + lastBallY - ballHeight/2);
         g.fillOval(drawX, drawY, ballWidth, ballHeight);
         
         lastDrawX = drawX;
         lastDrawY = drawY;
         
         g.setColor(Color.BLACK);
         g.drawString("FPS: " + fps, 5, 10);
         
         frameCount++;
      }
   }
   
   private class Ball
   {
      float x, y, lastX, lastY;
      int width, height;
      float xVelocity, yVelocity;
      float speed;
      
      public Ball()
      {
         width = (int) (Math.random() * 50 + 10);
         height = (int) (Math.random() * 50 + 10);
         x = (float) (Math.random() * (gamePanel.getWidth() - width) + width/2);
         y = (float) (Math.random() * (gamePanel.getHeight() - height) + height/2);
         lastX = x;
         lastY = y;
         xVelocity = (float) Math.random() * speed*2 - speed;
         yVelocity = (float) Math.random() * speed*2 - speed;
      }
      
      public void update()
      {
         lastX = x;
         lastY = y;
         
         x += xVelocity;
         y += yVelocity;
         
         if (x + width/2 >= gamePanel.getWidth())
         {
            xVelocity *= -1;
            x = gamePanel.getWidth() - width/2;
            yVelocity = (float) Math.random() * speed*2 - speed;
         }
         else if (x - width/2 <= 0)
         {
            xVelocity *= -1;
            x = width/2;
         }
         
         if (y + height/2 >= gamePanel.getHeight())
         {
            yVelocity *= -1;
            y = gamePanel.getHeight() - height/2;
            xVelocity = (float) Math.random() * speed*2 - speed;
         }
         else if (y - height/2 <= 0)
         {
            yVelocity *= -1;
            y = height/2;
         }
      }
      
      public void draw(Graphics g)
      {
         
      }
   }
}

Use whatever type of loop makes sense to you, but make it once and then reuse it everywhere! I’ve even seen people use both fixed timestep and variable timesteps together in the same game - do whatever makes sense!

And I think that’s it. Please everyone, include questions, comments, and corrections. Much of this code has not been run, and I’m sure there will be a lot of opinions about adjustments.

One weakness of that fixed timestep that could be implemented:

If your game lags or dips for a period of time, it will play catch up until it matches the amount of lost time. I have a fix for that somewhere, it’s pretty easy. If I get around to it I’ll edit the post.

Oh wow! I love your last example of the loop playing catch up until it matches the amount of lost time! I will implement that in my game engine. Thanks! :slight_smile:

Hi, Eli. Nice work on the tutorial. How about making it the first post in the shiny new Articles & tutorials section?

Here are some random comments and bits of feedback for you to disagree with and ignore. :wink:

  • It’s down to personal preference of course, but for variable time steps I prefer to pass the elapsed time in seconds (a double obviously) to the update function, rather than a ‘delta’ relative to a nominal time step (1/60th of second in your code). My reasons: If you’ve got a game object that works on a timer (e.g., a bomb that detonates after five seconds) then it’s nice if the code doesn’t have to keep converting back and forth between seconds and nominal time steps. Also, you don’t have to rewrite lots of code if you want to change the value of the nominal time step. As I say, personal preference, but I thought I’d make the case for the alternative approach.

  • It took me a while to realise that you’re talking about fixed time steps with respect to the update function only. I would argue that a game loop that uses fixed time steps for both updating and rendering is the most newbie-friendly approach. Any chance of including an example of that in the tutorial? I know that getting perfectly smooth results that way can be difficult, but I think it’s better for beginners than trying to struggle with either variable time steps in the update function or interpolation in the render function.

  • How about making all examples implement the same bouncing ball demo? That would let people compare the different approaches more easily. It would be even better if there were links to the examples running as applets/webstart so people have evidence that the code works as advertised on their machine.

  • (I’m not entirely sure this is a good idea, but if in the example update functions you added long delays (sleeps) at random intervals, that would demonstrate how good the game loop is at remaining smooth in adverse conditions.)

  • Is there a reason for not using BufferStrategy in the examples?

  • Gravity.ACCELERATION not Gravity.VELOCITY in the variable time step example.

  • I think it’s important in a variable time step loop to impose a maximum on the time step value passed to the update function (1/10th of a second, say). If the game hits a delay longer than the maximum then it’s not going to feel smooth whatever you do, and I bet that a lot of update functions will behave strangely when the time step is unexpectedly long (bullets will jump straight over aliens, Mario will fall through the platform below him, etc.).

  • In the variable time step example, the argument to Thread.sleep() can go negative. I don’t know how the function reacts to that (although presumably it does nothing).

  • The Ball class in the fixed time step example is never used.

  • In the fixed time step example, I don’t think it’s possible for the following clause to be executed (now is always greater than lastUpdateTime).

if (lastUpdateTime - now > TIME_BETWEEN_UPDATES)
{
  lastUpdateTime = now - TIME_BETWEEN_UPDATES;
}

  • I’ve never tried using interpolation in the render function, but I can’t help feeling that it might introduce some strange glitches unless you’re very careful. For instance, if you’re interpolating between the player being alive in one position, and dead in another position, there’s a danger that the player’s corpse might appear to jump around the screen briefly. Is this a problem in your experience?

Cheers,
Simon

Adding on Simon’s (dishmoth’s) post, you are depending on two threads for game loop and drawing which could cause some trouble since it might be in the middle of redrawing when it sets a new interpolation value and thus your redraw is completely thrown off. Maybe synchronized the methods or just use 1 thread for logic and render?

Thanks for all those comments, Simon! I’ll definitely put some of them in as I get the time, especially putting the ball example in for other examples. I agree that’s a great idea, especially having applets bundled with them too.

@ra4king: Which example are you referring to? I don’t think any of them have a separate thread for rendering and updating.

You call repaint(), which means you use passive rendering, depending on the EDT (Event Dispatching Thread) to call paintComponent(). Your game loop, meanwhile is in another thread that you start inside runGameLoop(). It is recommended, for more professional games that use Java2D, to use BufferStrategy and have game logic and rendering in the same thread.

EDIT: Oh and I am talking about your Bouncing Ball example :slight_smile:

Ah yes, this is true. I merely did that because it was quick to implement and I figured the most newbies would understand the paintComponent/repaint model. I had to include something actually happening to illustrate how to do interpolation with your drawing. But who am I kidding, people will likely just copy/paste the code, so I’ll put in a better method at some point. :slight_smile:

Yes I was fearing the copy/paste part :smiley:

I’ve been doing some testing over at this link, a complaint about jitteriness in a game loop:
http://www.java-gaming.org/index.php/topic,24311.0.html

I wish to toss some comments and challenges to Eli!

  1. for using a util.Timer, consider using the form that tries to keep the scheduled repeats based on the starting time, as in:
myTimer.scheduleAtFixedRate(new GameLoopIteration(), 0, 20);

The usual method, “myTimer.shedule(new GameLoopIteration(), 0, 20);” bases the next iteration time on the completion of the previous iteration, and thus can drift. “ScheduleAtFixedRate” will still be stuck with using the OS time granularity, but it will alternate between the enclosing trigger times. Example: timer repeat request: 20msec. System clock granularity: 15msec. The timer will trigger either at intervals of 15 or 30, depending upon whether it is running ahead or behind.

  1. Sleep is still dependent upon the constraints of the system, even if you have “Thread.sleep(1)” as you do in your “good” game loops. According to my tests, it seems there is no guarantee that the sleep will not occasionally last a full increment of the OS timing system. As I show (reply #15 in the above quoted thread) in some nano measurements of sleep(1), the sleep occasionally lasts 15msec. (The 15msec granularity I get is part of Windows XP OS.)

I have an idea that I am going to try as an experiment, to schedule absolute times via a util.Timer. Let’s see if the initiation of a scheduled TimerTask, given an absolute time, is implemented to be more accurate than the OS constraints. It will be like laying train tracks just ahead of the moving train. I did it before with some sound structures.

EDIT: nope, laying out absolute times for the timer tasks at 20msec intervals still resulted in iterations going back and forth between 15.5 and 31 msec iterations. :frowning:

Thanks a lot for the comments and challenge. It is indeed a challenge to get it absolutely perfect, and I agree that using Timer is not the best way to go. Instead, I would use yield() and one of the last two loops I posted, and maybe put in Thread.sleep(1) if you’re worried about using too much processor.

Try having a thread that sleeps forever like this:


new Thread() {
    public void run() {
        try{
            Thread.sleep(Long.MAX_VALUE);
        }
        catch(Exception exc) {}
    }
}.start();

That forces Java to use the high resolution timer, which makes sleep(1) MUCH more accurate.

Perils of running a conversation in two places…the code shown by avm1979 tested to work perfectly for me. I put some test results on the other thread…mentioned prior.

@ra4king, your example worked perfectly, as well! Every sleep measured out to within a single msec. That’s good enough for me. So, appreciations to you both.

Also, after reading your reply, I did a search on “high resolution Timer java” and found this thread:
http://www.java-gaming.org/index.php?topic=1071.0
So, it seems sun.misc.Perf is still around. I found it in the basic library: rt.jar. I’m going to test that next. Also, came across the suggestion that a ScheduledThreadPoolExecutor is an improved Timer and works. More stuff to test!

P.S., avm1979’s idea of making the background sleeper a daemon makes good sense, and if you aren’t already doing this, consider adding that fine point. Example on the link below, post #16.
http://www.java-gaming.org/index.php/topic,24311.0.html

Ah yes I have seen both posts.

And what’s a daemon and how would it help? O_o

http://www.jguru.com/faq/view.jsp?EID=43724

Ah makes sense thanks!

I have a bit of an issue when your game consists of more than just bodies moving at fixed (non changing) velocities.

Say you introduce acceleration. Suddenly, linearly interpolating the drawx and drawy doesn’t make any sense, since the velocity of your ball has changed between frames A and B.

Additionally, what happens when you start to introduce shifts in color over time? Say we have an effect that is placed on an entity that changes its texture color from white to red slowly over 5 seconds. Obviously its more noticeable when things are jittery position-wise, but in a truly interpolated fixed timestep system, is the only way to achieve perfect accuracy to interpolate each and every thing that can undergo a change before it is drawn?

You have to keep in mind that human senses are limited. Certain mathematical niceties are simply too small to discriminate. So, in a lot of situations linear interpolation is good enough, especially if you have a healthy frame rate going.

[Added] There is a minimum color distance that is observable as a discontinuity. This minimum distance might be numerically different depending upon where in the color space you are located. Often the relationship between perception and the numbers used to traverse a space is logarithmic rather than linear.

Also, there are a number of “color spaces” to choose from besides RGB for color traversal, which has to be considered.

In any case, the amount of change between frames should to be below the amount that triggers a perceptual discontinuity, or you will get some sort of artifact. So you have to be responsible for knowing what that minimum is and providing some sort of throttle or max delta function (if you want to avoid the discontinuities).

Right. So I guess by the sound of that, the interpolation of positions of bodies/images/particle emitters in the game, as well as angles, is enough for human detection. I guess this makes sense, especially when you consider you’re talking about sixtieths of a second.

What about interpolating the position of the viewport for a GL Lookat call?

It doesn’t matter what you do as long as you have one frame of latency. You interpolate between whatever the last displayed values were (position/color/scale) and the current ones. Whatever caused the changes in positions doesn’t matter because you’re only ever directly representing position itself.

Make sense?