Bouncing Balls

I am writing a simple bouncing balls animation, where the balls bounce off the walls and the other balls. I am following the worm example from “Killer Game Programming in Java”. Here is my main game loop:


	public void run() {
		long beforeTime, afterTime, timeDiff, sleepTime;
		long overSleepTime = 0L;
		int noDelays = 0;
		long excess = 0L;
		
		Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
		isRunning = true;
		
		gameStartTime = System.nanoTime();
		prevStatsTime = gameStartTime;
		beforeTime = gameStartTime;
		
		while (isRunning) {						
			nextFrame(period/1000000L);
			updateDisplay();
			
			afterTime = System.nanoTime();
			timeDiff = afterTime - beforeTime;
			sleepTime = (period - timeDiff) - overSleepTime; 
			
			if (sleepTime > 0) {
				try {
					Thread.sleep(sleepTime / 1000000L /* nanosecs -> ms */); 
				} catch (InterruptedException ex) {
					// do nothing
				}
				overSleepTime = (System.nanoTime() - afterTime) - sleepTime;
			} else { // sleepTime <= 0; the frame took longer than the period
				excess -= sleepTime;  // store excess time value
				overSleepTime = 0L;
				
				if (++noDelays >= NO_DELAYS_PER_YIELD) {
					Thread.yield();   // give another thread a chance to run
					noDelays = 0;
				}				
			}
			
			beforeTime = System.nanoTime();
			
			/*
			 * If frame animation is taking too long, update the game state
			 * without rendering it, to get the updates/sec nearer to the
			 * required FPS.
			 */
			int skips = 0;
			while ((excess > period) && (skips < MAX_FRAME_SKIPS)) {
				excess -= period;
				nextFrame(period/1000000L); // update state but don't render
				skips++;
			}
			framesSkipped += skips;
			
			updateStats();
		}
	}

And here is my the code for updating the animation state:


	public void nextFrame(double t) { // t is in microseconds
		if (isPaused) return;
		
		// t is the time of the earliest collision.
		// if t == RATE then there are either no collisions
		// or collision occur at time RATE		
		// Since only the earliest collision needs to be found,
		// the collision test are performed for the current 
		// time of the earliest collision (t).
		
		// Test for wall collisions
		for (int i = 0; i < balls.length; i++) {
			t = Math.min(t, balls[i].testWallCollision(t));	
		}
		
		// Test for ball collisions
		// collision are added to the head of this list		
		List<Collision> collisions = new LinkedList<Collision>();
		Ball a, b;
		for (int i = 0; i < balls.length; i++) {
			a = balls[i];
			for (int j = i+1; j < balls.length; j++) {
				b = balls[j];
				t = Math.min(t, a.testBallCollision(b, t, collisions));	
			}
		}
		
		// Move the balls
		for (int i = 0; i < balls.length; i++) {			
			balls[i].move(t);
		}
		
		// Handle the collisions that occured
		// NOTE: It is possible that two collision occurred at the
		// same time. Therefore the collision list is iterated
		// until we get to a collision that occured after the
		// time of the first collision
		for (Collision c : collisions) {
			if (c.t == t) {
				c.handle();
			} else {
				break;
			}
		}
	}

My problem is that I want the frame to update according to how much time has passed since the last frame. At the moment I just assign t to the period (converting to ms) . Should I pass in timeDiff from the last loop instead (for the first nextFrame call that is rendered)?

Also multiple collisions may have occured since the last frame. At the moment I update the state to the time of first collision (or t if no collisions occured). I should continue to handle collision until no collisions are left for the frame. However will this not likely mean the nextFrame() method takes too much CPU time before we paint the next frame? How should I be handling this?

Below is a modified nextFrame() that will repeat if the frame period has not expired. Is this the right way of doing this? Should I be checking CPU time that has elapsed?


	/**
	 * Creates the next frame
	 */
	public void nextFrame(double t) {
		if (isPaused) return;
		
		long startTime = System.nanoTime();
		
		double rt = t; // remaining frame time
		boolean isCollision = false;
		
		do {
			isCollision = false;
			
			// t is the time of the earliest collision.
			// if t == rt then there are either no collisions
			// or collision occured at time rt		
			// Since only the earliest collision needs to be found,
			// the collision test are performed for the current 
			// time of the earliest collision (t).
			
			// Test for wall collisions
			for (int i = 0; i < balls.length; i++) {
				t = Math.min(t, balls[i].testWallCollision(t));	
			}
			
			// Test for ball collisions
			// collision are added to the head of this list		
			List<Collision> collisions = new LinkedList<Collision>();
			Ball a, b;
			for (int i = 0; i < balls.length; i++) {
				a = balls[i];
				for (int j = i+1; j < balls.length; j++) {
					b = balls[j];
					t = Math.min(t, a.testBallCollision(b, t, collisions));	
				}
			}
			
			// Move the balls
			for (int i = 0; i < balls.length; i++) {			
				balls[i].move(t);
			}
			
			// Handle the collisions that occured
			// NOTE: It is possible that two collision occurred at the
			// same time. Therefore the collision list is iterated
			// until we get to a collision that occured after the
			// time of the first collision
			for (Collision c : collisions) {
				if (c.t == t) {
					c.handle();
					isCollision = true;
				} else {
					break;
				}
			}
			
			// calculate frame time renaming
			t = rt - t;
			rt = t;
			
		// continue updating frame if there was a collision and the frame period has not expired
		} while(isCollision && rt > 0 && System.nanoTime() - startTime < period); 
	}