If this is your first visit, be sure to
check out the FAQ by clicking the
link above. You may have to register
before you can post: click the register link above to proceed. To start viewing messages,
select the forum that you want to visit from the selection below.

For both of those I get 17 frames per milliseconds. The second one is a little bit more jittery and I think that has to do with the DoEvents there. There are even times where it spikes up to 30 frames per millisecond.

Last edited by dday9; Dec 24th, 2013 at 11:38 AM.
Reason: Took out the VB.Net prefix.

Re: GameLoop theories!

Ooooh but there are far better ways to do a game loop my friend. And I'm about to unleash my own personal secrets. Games have not just the game itself, but also an Intro, a Title Screen (with options), sometimes a demo, a loading screen, and even an ending (not to mention collision detection, ai, controls, physics, and a bunch of other things), all managed by one entity...the main game loop. And it must be locked at 60 frames per second. Unless you live in Europe where the standard is 50 frames per second. To lock the framerate at any given rate, you do this:

Unless you use DirectX, then it locks the framerate for you. Once your game gets more complex and you wanna add more things, you break it up a notch:

vb.net Code:

PrivateEnum GAME_STATUS

INTRO = 1

TITLE_SCREEN = 2

LOAD_SCREEN = 3

GAME_WORLD = 4

ENDING = 5

EndEnum

Private Status as GAME_STATUS

...

PrivateSub Game_Loop()

DoWhile Running = True

SelectCase Status

Case INTRO

Intro_Loop

Case TITLE_SCREEN

Title_Screen_Loop

Case LOAD_SCREEN

Load_Screen_Loop

Case GAME_WORLD

Game_World_Loop

Case ENDING

Ending_Loop

EndSelect

Lock_Framerate(60)

Me.Text = Get_FPS()

Application.DoEvents()

Loop

EndSub

Where the Intro_Loop, Title_Screen_Loop, Game_World_Loop, etc., are their own sub routines that contain all the code done in the main game loop. But the subs DO NOT contain their own endless Do loops. That would defeat the purpose of what we are doing and the frame rate would not be locked because you are stuck in another endless loop. The subs only contain the code that is executed over and over related to the game. Doing this would help you build an entire game with these entities from start to finish. And you can lock the frame rate at any given rate desired, even for debugging purposes which helps a ton. I not only do this code for VB6 and VB.NET, but also C++ as well. It works. I hope this helps.

Re: GameLoop theories!

Let me ask you this Jacob, I know why it's important to have a game locked in at a certain FPS, but why is the target at 60(or 50 in Europe)? I never quite got why it should be at 60 and not at say... 40 or hell even 120.

Re: GameLoop theories!

What's your screen refresh rate? 60Hz, right? (As indeed is your electricity supply.) There's no point having an FPS greater than that because it would simply fail to show some frames altogether. And if its lower than that it could go out of phase with the possibility of visual glitches. In Europe the power supply is 50Hz and the refresh rate has usually matched it. Having said that I'm now running a 60Hz refresh rate (my display settings won't allow me not to!) so I'm not sure whether it's still strictly necessary to change the target fps to suit us Right Pondians.

As the 6-dimensional mathematics professor said to the brain surgeon, "It ain't Rocket Science!"

Reviews: "dunfiddlin likes his DataTables" - jmcilhinney

Please be aware that whilst I will read private messages (one day!) I am unlikely to reply to anything that does not contain offers of cash, fame or marriage!

Re: GameLoop theories!

Oh ok, that makes sense. Because I was looking at reviews on some different processors and I saw that they were saying: "Oh with this processor I had blah blah blah amount of FPS" and I'm thinking ok so it's better to have a higher FPS? But really it's all dependent on the screen's refresh rate then.

Re: GameLoop theories!

Originally Posted by dday9

Oh ok, that makes sense. Because I was looking at reviews on some different processors and I saw that they were saying: "Oh with this processor I had blah blah blah amount of FPS" and I'm thinking ok so it's better to have a higher FPS? But really it's all dependent on the screen's refresh rate then.

Exactomundo. And if you work with DirectX, it does it for you. No locking framerates necessary. And whats good about my code on locking the framerate is that you can slow it down to lets say 10 FPS for debugging purposes.

Re: GameLoop theories!

See XNA has a managed game loop built in... if you use the GameStudios which is only available for C#. This forced me to think of ways for game loops. Now with XNA being no more... I'm trying to expand my options.

Re: GameLoop theories!

Thought you should know that TimeGetTime is not necessarily consistent across all hardware and versions of Windows, so may or may not give you 60hz using Jacob's code.
I've gotten to use a lot of different computers, and Windows (or the hardware manufactures) lack of consistency when it comes to the clocks behind these various API calls has been a real thorn in the side.
Just when you think you have a simple timing solution, you find a machine that doesn't work.
In this case, I tried it on an HP EliteBook 8470p laptop (running Windows 7 Enterprise 64-bit), and I asked for 60hz, but was getting 32hz.
I investigated and found that the time returned by the timeGetTime function incremented at 64hz, i.e. some example deltas
35006709, 35006709, 35006709,..... doesn't matter how often you read it in the loop, it won't change until
35006724, 35006724, 35006724,..... 15.625 milliseconds has passed....
35006740, 35006740, 35006740,.....

So, what happens is we try to wait for 16.666 milliseconds to pass, and the timeGetTime changes just short of that, so we continue to wait, and it doesn't change again until another 64hz period has passed, at which time we see we've exceeded the 16.666 milliseconds (by quite a bit) and return.
The result is, we always wait two 64hz periods, so are running at 32 hz.

One way to improve on that situation is to establish a base time, and add the "trigger" time to that.
Instead of
31. Last_Time = timeGetTime
you have
31. Last_Time += 1000/Target_FPS

The result is you will average 60 hz over time. In this case, the code will run at 64 hz for around 11 passes (15 to 16ms), and then 32hz for 1 pass(31 ms)
and repeat.
You need a safety check to initialize the Last_Time, and in case of debugging, or some other reason your code gets delayed and you miss a number of frames, you reset the Last_Time to re-sync to the current time.
Since we expect one time period out of 11 to be almost twice the target_FBS, we'll set the limit to be three times the target_FBS interval (i.e. if the update was less than 20hz, reset the Last_Time value)
If ((Current_Time - Last_Time) > (3 * (1000 / Target_FPS))) Then Last_Time = Current_Time

Bottom line, you can't always trust that timeGetTime will return 1 ms resolution, or even close to it.

Re: GameLoop theories!

Originally Posted by dday9

What happens if you run my very first example?

I'm on a different machine now, but I did a quick test to see what interval I was getting on timeGetTime to see if I could use this laptop as a test platform, or wait until I was back on the machine that had the 64hz based interval.
The interesting thing on this machine, is that it looks like it is mostly 100hz based, with the millisecond interval being 10ms for a good portion of a second.
But then it will drop to 1ms resolution for a series, up to 22 times in a row, then return to 10ms. On this machine I never saw it slower than 10ms, but testing 400 loops (which would be about 4 seconds at 10ms), showed that it increased to 1ms resolution for several streaks, but never in a consistent pattern. it would also have short breaks (usually only 3 or 4 times through the loop) where it would be some other smaller number, in the range of 2 to 4ms.

Anyway, since it wasn't a consistent 1ms resolution, being 10ms the majority of the time, it seemed an acceptable surrogate for the other computer.
Using your first code, based on JMcIlhinney's pauser code, it behaved as I would expect, with erratic timing, the majority of the time being around 20 to 27ms (JMc's pause time (17) + the 10ms coarseness of the timer, dropping to 17ms or so when the timer dropped to 1ms resolution).
Your second code in the first post was a very consistent 17ms, because the stopwatch object on most of the machines I've tried is very consistent, and when I tested the stopwatch earlier with my timing test (I only tested the millisecond accuracy), it was consistent at 1ms. It actually would probably be accurate to some sub-millisecond value, if I looked at the frequency of Tick change, but I didn't).
I removed the Applications.DoEvents call from your second code, because that loop is on a background thread so what purpose would calling DoEvents have on a background thread (other than possibly, as you suspected, introduce some connection back to the GUI thread, making the timing inconsistent).
The way the background thread is used is the main drawback of that code (in my opinion), since it is launching and exiting a background thread for every loop, which is a lot of resource thrashing.

The simplest and best timing on this machine (and I will have to relook at the other machine to check its stopwatch accuracy), is to simply replace the timeGetTime call in Jacob's code with a stopwatch.ElapsedMilliseconds call to get a very well behaved locked frame rate, the vast majority of the time. It definitely would appear, given the half dozen or so machines that I've tried it on over the last two years, is that the stopwatch is more likely to give a reasonable result compared to timeGetTime. The stopwatch object uses the high resolution timer tick count, if it is supported, so is based on the same source that the unmanaged API calls QueryPerformanceFrequency and QueryPerformanceCounter are based.
The only caveat (which also applies to QueryPerformanceCounter), is that on multi-processor machines, the counter value can be different depending on which core the thread is running on, so you would want to specify processor affinity for a thread, with the ProcessThread.ProcessorAffinity method, to have consistent timing at the possible cost of performance loss by the system not being able to switch your thread to a lighter loaded processor (but hopefully keeping the processors balanced by moving threads off "your" processor that aren't tied to a particular processor, so keeping the impact of your desire to stick to one processor at a minimum.

Re: GameLoop theories!

Guys guys lol. I posted the wrong code. Must have been drunk cause that was an old and obsolete program. I don't really use the timeGetTime for my game loops so don't sweat it. I was just rushing out the answer

I always use the QueryPerformance APIs. 60 frames per second every time. Sorry for the mishap, I don't want the thread to stretch on over it :rollseyes: