Sign in to follow this  
Followers 0
CdrTomalak

Controlling game loop speed

10 posts in this topic

My pacman clone is progressing, and I am now at the point where I need to slow down the game loop.

 

However, there are points where I switch textures which causes a subtle slow-down (I think - it's hard to tell), so my thoughts turn to regulating the game loop speed - i.e. I don't want to see any slowdown whatsoever.

 

Rather than putting a wait command in the loop, what other techniques are there? I'm sure there are loads out there, so please feel free to point in the way of your favourite article. I'm basically doing research at the moment before going ahead with anything.

 

Essentially I want to choose a game speed which means there will always be room for a little extra processing overhead, and the user will not notice a thing. It's running too fast at the moment! On average about 350 FPS.

 

Thanks in advance! cool.png

Edited by CdrTomalak
0

Share this post


Link to post
Share on other sites
Yep, neither a busy wait nor a Thread.Sleep would be I good idea. The former wastes cycles and the latter has too big a granularity so you might drop frames.
 
Do a VSync, in D3D9 this is done with PresentInterval.One (PresentParameters of the device or SwapChain), in D3D11 with SwapChain.Present(1,PresentFlags.None);
2

Share this post


Link to post
Share on other sites

unbird and Servant - thanks for the advice!

 

So I just tried this as a first foray into FPS regulation. Results are ... not great!

 

So before my game loop I call this code:

 

			int FPS_TARGET = 150;
			int SKIP_TICKS = 10000000 / FPS_TARGET;			
			int TICKS_BEFORE_GAME_LOOP = getTickCount();	
			int TICKS_PASSED = 0;
			int TICK_TARGET = 0;
			int TICKS_NOW = 0;
			int TICKS_TO_WAIT = 0;
			TimeSpan timeSpan;

Then after the game operations, at the end of the loop I call:

 

					//		Tick target = Ticks BEFORE game loop + how many ticks to equate to desired FPS
					TICK_TARGET = TICKS_BEFORE_GAME_LOOP + SKIP_TICKS;
					// Get the tick count right now
					TICKS_NOW = getTickCount();
					// Find out how many ticks have passed
					TICKS_PASSED = getTickCount() - TICKS_BEFORE_GAME_LOOP;
					// Find out how many ticks we should wait
					TICKS_TO_WAIT = TICK_TARGET - TICKS_NOW;
					// Create a time span object so we can esily derive the milliseconds to wait
					timeSpan = new TimeSpan(TICKS_TO_WAIT);

					// Now sleep for the desired number of milliseconds	
					if(timeSpan.Milliseconds > 0)
					{
						// We're going to fast so slow down.
						Thread.Sleep(timeSpan.Milliseconds);
					}
					else
					{
						// We're running slow
					}

Initially this looks like it is working, but then later on the game starts going to fast again. I've got some timers in my game already, and confess to not really understanding threads that much (all the work has been on the game engine and logic so far...), so I am going to look into why my method is failing terribly!

 

As I said, new to this FPS regulation stuff. Trying a few things out is teaching me about various pitfalls etc (I seem to like learning that way!) cool.png

0

Share this post


Link to post
Share on other sites

Well I said you shouldn't use Thread.Sleep wink.png. Get accurate timing first. You can e.g. use the System.Diagnostics.Stopwatch: Start it at program start and use the Elapsed property.

 

Edit: As Servant pointed out. You use the delta to "feed your simulation", not the other way round.

 

Now: Even the Stopwatch normally has a granularity which might pose a problem (15 ms if memory serves). Check if Stopwatch.IsHighresolution is enabled, it usually is. You will have to do the conversion yourself with (double)Stopwatch.ElapsedTicks / Stopwatch.Frequency.

Edited by unbird
1

Share this post


Link to post
Share on other sites

Well I've tried to implement FPS control using a timer, but it's not working for some reason I cannot fathom.

 

I am succesfully calculating the "MS to wait after every frame until proceeding to the next iteration of the game loop". Now then - having already tried Thread.Sleep() with dodgy results, I thought using a time would help.

 

I've got a setting to enable me to switch between timing modes. The code for using a timer is as follows:

 

	
        nextFrame = false;

        if(FPS_METHOD == "TIMER")
	{		
		// -----------------------------------------------------------------
		// TIMER METHOD (awful at present
		// -----------------------------------------------------------------
		if(GLOBAL_MS_TO_WAIT > 0)
		{		
			// START TIMER
			StartFPSTimer();	// Sets MS passed to 0
			
			// Wait until the nextFrame flag has been set. This will be when we reach the desired number of MS.
			// This is detected in the event MSecondHasPassed().
			do
			{
				// nothing
			} while (!nextFrame); // nextFrame will always be true after exiting this loop.
		}
		else
		{
			// We're running SLOW.
		}
	} // TIMER METHOD

Now in the game initialisation code I call the following to set up the FPSTimer:

 

		public void CreateFPSTimer()
		{
			// This timer needs to be tied to an event which fires every time a MS passes, not a second.
			FPStimer = new System.Threading.Timer(new System.Threading.TimerCallback(MSecondHasPassed), null, 0, 100);
		}

I declare the event as follows:

 

		private void MSecondHasPassed(object obj)
		{			
			// Increase the seconds passed counter.
			MsecondsPassed++;
			
			// Set nextFrame flag if MS passed is at the threshold
			if(MsecondsPassed == GLOBAL_MS_TO_WAIT)
			{
				nextFrame = true;
			}
		}

So what I'm doing is just waiting for the flag to be set via the event per MS. It looked easy to implement.

 

I *think* my timer is not declared correctly because the game slows to an unbearable pace. I thought it was declared correctly but it can't be. Is there something painfully obvious that I've got wrong?

0

Share this post


Link to post
Share on other sites

Why are you insisting on regulating your framerate? That's kind of a backwards approach to the issue, which is that you don't use real wall-clock time to control your simulation speed.

0

Share this post


Link to post
Share on other sites

Well basically I'm trying to slow the game down. The design is quite (read very) primitive really. I'm just starting out and whilst I have a fairly solid game engine, I need to control the speed of the game loop.

 

Whilst really I should go with an overhaul to bring the design up to speed with best practice (updating movement based on time passed) I thought a quick fix for now would be to regulate the FPS.

0

Share this post


Link to post
Share on other sites
I strongly recommend biting the bullet and writing the code correctly. As far as I'm aware you're under no specific deadline, so there's no reason to do something you explicitly know is inferior :-)
0

Share this post


Link to post
Share on other sites

My first game iteration plan includes quick-win options, as the quality of the first game is not supposed to be A1 but server as a learning exercise. I would imagine that the 2nd pass, or phase 2 would include using deltas and doing things correctly. Although I am under no specific deadline, I do want to draw Phase 1 to a close.


The next task after controlling game speed is to introduce sound, which I'm placing a higher priority on than a full rework to control game speed correctly. I guess it depends what's on your plan is for the implementation - and they are always pretty individual. I'd favour a patch-up for now. Just a preference though, and I'm sure others will disagree. If I can patch it up for minimal effort and it runs OK from the users point of view then that's fine for now.cool.png

0

Share this post


Link to post
Share on other sites

If you don't want to change much:

Just use a simple(not optimal, but very simple) fixed timestep then: (If you want to do it properly, read this: http://gafferongames.com/game-physics/fix-your-timestep/ )

 

add:

double currentTime, lastTime;

const double timePerFrame = 16.66667; //60 updates per second, roughly

currentTime = lastTime = systemfunctiontogetcurrenttimeaccuratly();

before your main loop.

 

and 

currentTime = systemfunctiontogetcurrenttimeaccuratly();

if (currentTime - lastTime < timePerFrame) continue;

lastTime+=timePerFrame;

//update and render normally here

 

at the top of your mainloop (inside the loop, just after the while)

 

set timePerFrame to whatever makes your game run at the speed you want.

0

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0