Original Post
Hey everyone, I recently started on a small snake game in java and so far everything is coming along fine. Everything, except for this very odd phenomenon that keeps occurring more often than not when running the application. I use System.nanoTime() for the timing in my application and every tenth of a second I update the movement of my snake. According to my calculations, everytime when 'timeElapsed' reaches 10^8 nanoseconds I should update. Sometimes this yields the intended results, but like I said, more often than not it doesn't yield the intended results. At these times the movement of the snake will be twice as slow. I have also included a small explosion animation for when the snake hits the walls or itself and this animation takes twice as long as well. This is easily measurable since I have specified the animation to run for 1500 milliseconds and whenever the application is in it's 'slow mode' it takes around 3 seconds to complete. As of yet I have discovered no means of influencing the speed at which the application updates the snake movement and animation other than running multiple instances of the application at the same time. The first instance will have a slow snake and a slow animation, the second instance (leaving the first one open) will have small 'speedups' where the update-speed will sometimes go to normal for a small time and then return to being slow. At around the third instance and more the update speed will be entirely normal for both the snake and the animation. I find this pretty odd... Since this will probably sound very vague I have uploaded a .jar with the game as it currently is. You can download it from http://www.digillusions.com/Snake.jar. Since I suspect this to be some sort of timing problem I'll quickly explain the game loop and method of updating I use. Basically I use a somewhat modified version of the GamePanel class that is introduced in "Killer game programming in Java" by Andrew Davison. When the application starts, it creates a new thread in which to run the game loop. Thus, the 'run' method looks like this: I am subclassing GamePanel and overriding the update and paint methods for each specific application, and the update method for this snake game looks like: As you can see, every tenth of a second the game is 'updated' but judging by the observable behaviour of the application a tenth of a second is a very relative amount of time... I hope I have provided enough information on the problem, if not I'll be happy to provide more. Regards, Rogier Pennink
while ( running )
{
/* Get the current time. */
before = System.nanoTime();
/* First update the game state. */
update( diff + ( ( sleeptime > 0 ) ? sleeptime : 0 ) );
/* Then do the painting. */
paint();
/* Flip buffers. */
flip();
/* Get the current time and calculate time difference between last and current frame. */
after = System.nanoTime();
diff = after - before;
sleeptime = ( (long)( 1000.0 / targetFPS ) * 1000000L ) - diff;
framecount++;
/* Update the FPS. */
elapsedtime += diff + ( ( sleeptime > 0 ) ? sleeptime : 0 );
if ( elapsedtime >= 1E9 ) /* If one second passed. */
{
actualFPS = framecount;
elapsedtime = 0L;
framecount = 0;
}
/* Attempt to sleep a little bit, if we don't manage to get some sleeptime once in a while
* we'll yield after that happened 16 times. */
if ( sleeptime > 0 )
{
try
{
Thread.sleep( sleeptime / 1000000L ); /* Nanoseconds to Milliseconds. */
}
catch ( Exception e )
{
e.printStackTrace();
}
}
else
{
if ( ++nodelays >= 16 )
{
Thread.yield();
nodelays = 0;
}
}
}
protected void update( long timedelta )
{
timeElapsed += timedelta;
if ( timeElapsed >= 1E8 )
{
/* Update the level. */
level.update();
timeElapsed = 0L;
if ( !level.willDie() )
{
level.getSnake().move();
}
else
{
if ( !explosion.isRunning() ) explosion.startAnimation( false );
state = GameState.GAME_LOST;
}
}
if ( state == GameState.GAME_LOST )
explosion.update( (int)(timedelta / 1000000) );
}