Rate my Game Loop

Started by
7 comments, last by wintertime 9 years ago

Hello there! I have started to make a game in Java, and I would appreciate some comments on my Game Loop.

It basically limits the amount of update calls that are made to 60 per second, allowing the render calls to be unlimited. I am not sure if this is the ideal approach as I don't have a background in Game Programming. Would it make more sense to limit the render method too?

public void run() {
final float updates = 1000000000/60; // 60 ups (updates por segundo)
float prevUpdate = System.nanoTime();
float diff, timeNow;
float delta = 0, delta2 = 0;
int ups=0,fps=0;
while(isRunning){
timeNow = System.nanoTime();
diff = timeNow-prevUpdate;
prevUpdate = timeNow;

delta2+=diff;

delta+=diff; // delta holds the time since the last update

if(delta2>1000000000){ // OPTIONAL: I use it to calculate fps and ups
updateFrames(fps,ups);
delta2 = 0;
fps=0;
ups=0;
}

if(delta>=updates){ // delta resets 60 times per second( and update is called)
delta = 0;
update();
ups++;
}

render(); // the render method isnt limited
fps++;



}
}

private void updateFrames(int fps, int ups) {
System.out.println("FPS: "+fps+" UPS: "+ups);

}

Advertisement

What you want to do is fix your timestep. This ensures your game's simulation behaves identically given the same input, even if frame rates differ. For example, a person with a slow computer vs a person with a super high-end computer.

Hello to all my stalkers.

Also, this is a minor nit, but try to avoid magic numbers like 1000000000, you should make that a const somewhere and name it something more meaningful.

So far, it looks pretty good. Again, I'd like to reiterate what ferrous said: avoid magic numbers! He says it's a minor nit, but as you develop software further, you will grow to regret using numbers like that.

Also, i suggest using the code tags when posting code. It just makes it easier to read. :D

I develop to expand the universe. "Live long and code strong!" - Delta_Echo (dream.in.code)
Rating:
????? (2 of 5 stars)

Does not handle the spiral of death.
Would not recommend stepping time with programmer again.

---

In addition to what others have said, you may want to consider the case when the simulation can't keep up and must sacrifice updates to keep the simulation going. Otherwise, the simulation will grind to a halt.

Use the timer class as described here to avoid floating point precision issues. Then, one frame is just


UINT64 ui64CurTime = m_tRenderTime.Update();
while ( ui64CurTime - m_tLogicTime.CurTime() > FIXED_TIME_STEP ) {
        m_tLogicTime.UpdateBy( FIXED_TIME_STEP );
        //Update the logical-side of the game.
}
Render();

Thank you all for your fast answers. I have taken into account all your advices and modified my loop, basically making the delta variable to act as an accumulator which holds the time not consumed in the update operation.


	public void run() {
		
		float prevUpdate = System.nanoTime();
		float diff, timeNow;
		float delta = 0, delta2 = 0;
		int ups=0,fps=0;
		while(isRunning){
			timeNow = System.nanoTime();
			diff = timeNow-prevUpdate;
			prevUpdate = timeNow;
			
			delta2+=diff;
			
			delta+=diff; // delta calcula el tiempo a partir de el ultimo update()
			
			if(delta2>ONE_SEC_IN_NANOS){ // OPCIONAL: lo uso para calcular fps y ups
				updateFrames(fps,ups);
				delta2 = 0;
				fps=0;
				ups=0;
			}
			
			while(delta>=UPDATES){ // 60 veces por segundo se reinicia el delta y se ejecuta update, uso while para evitar que el update se retrase si los ups son inferiores a 60
				delta -= UPDATES; // los nanosegundos perdidosse guardan para la proxima iteracion, asi el estado del programa siempre es estable a 60ups
				update();
				ups++;
			}
			
			render(); // el metodo render no esta limitado, se ejecuta las veces que la maquina lo permita
			fps++;
			
			
			
		}
	}

I still have a question regarding the update function. I have seen in some examples that people pass a time variable as a parameter to the update function. I imagine it is to keep all the updates consistent(like the Time.deltaTime in Unity). But in the case of my loop where all the updates happen at the time of 1/60 seconds, would it be necessary?

@Irlan: In your post I could only find the Timer class for C++, but I am using Java. If you know an improvement for Java I would love to hear about it. Thanks anyways!

Thank you all for your fast answers. I have taken into account all your advices and modified my loop, basically making the delta variable to act as an accumulator which holds the time not consumed in the update operation.


	public void run() {
		
		float prevUpdate = System.nanoTime();
		float diff, timeNow;
		float delta = 0, delta2 = 0;
		int ups=0,fps=0;
		while(isRunning){
			timeNow = System.nanoTime();
			diff = timeNow-prevUpdate;
			prevUpdate = timeNow;
			
			delta2+=diff;
			
			delta+=diff; // delta calcula el tiempo a partir de el ultimo update()
			
			if(delta2>ONE_SEC_IN_NANOS){ // OPCIONAL: lo uso para calcular fps y ups
				updateFrames(fps,ups);
				delta2 = 0;
				fps=0;
				ups=0;
			}
			
			while(delta>=UPDATES){ // 60 veces por segundo se reinicia el delta y se ejecuta update, uso while para evitar que el update se retrase si los ups son inferiores a 60
				delta -= UPDATES; // los nanosegundos perdidosse guardan para la proxima iteracion, asi el estado del programa siempre es estable a 60ups
				update();
				ups++;
			}
			
			render(); // el metodo render no esta limitado, se ejecuta las veces que la maquina lo permita
			fps++;
			
			
			
		}
	}

I still have a question regarding the update function. I have seen in some examples that people pass a time variable as a parameter to the update function. I imagine it is to keep all the updates consistent(like the Time.deltaTime in Unity). But in the case of my loop where all the updates happen at the time of 1/60 seconds, would it be necessary?

@Irlan: In your post I could only find the Timer class for C++, but I am using Java. If you know an improvement for Java I would love to hear about it. Thanks anyways!

Oh, I see. Just search for the similiar functions in Java for QueryPerformanceFrequency and QueryPerformanceCounter.

You wrote you fixed it, but you still use float.

Floats are not a good datatype for time: https://randomascii.wordpress.com/2012/02/13/dont-store-that-in-a-float/

This topic is closed to new replies.

Advertisement