Game Timing & Alt-Tab?

BlitzMax Forums/BlitzMax Programming/Game Timing & Alt-Tab?

Sean Doherty(Posted 2007) [#1]
I'm using a mix of time stepping and delta time for game timing. However, there seems to be a problem caused by Alt-Tab?

Also, it looks like my time step code may be wrong. Anyone have any code they would recommend?

Thanks


Gabriel(Posted 2007) [#2]
I'm not sure what you mean by a mix of "time stepping and delta time".

Personally, I use this :

http://www.gaffer.org/game-physics/fix-your-timestep/


ninjarat(Posted 2007) [#3]
Also, alt-tab is often used by Windows to switch apps, and if that isn't happening, then it's probably just slowing down your timestep during the call to the Windows Power Tools process.


Grey Alien(Posted 2007) [#4]
you need to put some detection into your time stepping function that says if the delay has been great than say 100ms it's probably due to someone alt-tabbing or dragging the window or some massive intrusive system task, and then just use your last sensible loop value instead.


Sean Doherty(Posted 2007) [#5]
I tried pure time stepping before, but I could never seem to get the game to play smoothly. Anyway, I implemented it again and its not very smooth.

My frame rate is 85 hz and I have 2 - 3 updates per render.

Did you implement the alpha and integrate part? Any ideas why it would be smooth?

Thanks


Grey Alien(Posted 2007) [#6]
run this:

http://www.greyaliengames.com/misc/JerktesterGraph.zip

If you get lots of peaks instead of a basically flat line then nothing will run smooth on your PC because it has too many background tasks running.


Sean Doherty(Posted 2007) [#7]
Cool little program! I get an average of 11 and a peak of around 82. The peaks kind of show up every two or three passes.


Gabriel(Posted 2007) [#8]
If you get lots of peaks instead of a basically flat line then nothing will run smooth on your PC because it has too many background tasks running.

I don't know how you're deducing that statement, but I get an average of 16, a low of 4 and a high of 173, and a lot of games run very smooth, windowed and fullscreen.


Sean Doherty(Posted 2007) [#9]
I've noticed Max games seem to be a lot more effected my back ground tasks than other games? It least it seems that way?

Gabriel,

Are you willing to post your timing code?


CGV(Posted 2007) [#10]
I've noticed Max games seem to be a lot more effected my back ground tasks than other games.


This is without a doubt true. According to Grey's jerktester I have a hoplessly jerky system and yet it's only Max games that I notice any jerkiness in.

I've spent the past two days trying out all the garagegames titles to pick my freebie and I've been surprised every time by the smoothness of the animation and scrolling backgrounds.

In fairness I have seen some Max games that are super smooth on my system so obviously there is a way to achieve it but apparently those who have figured it out are keeping the secret to themselves. :(


Grey Alien(Posted 2007) [#11]
You can't count 3D games when testing smoothness as any jerks aren't easy to see. You need to test other 2D games, and there are plenty of jerky ones.

If you get lots of peaks on my jerk tester then you will have problems with BMax games (that use timing) and maybe others. If you only get the occasional peak then it may be OK.

BMax does seem affected by background tasks if you use delta timing or similar. If you just lock the Hz to the screen refresh (e.g. 60Hz in full-screen) then you WILL get a smooth looking game but then the game will run at a different speed in windowed mode. That why you HAVE to use some kind of timing (well it's one of several reasons).

Maybe at some point I should write the jerk tester in Blitz Plus to see if it's any more stable?


CGV(Posted 2007) [#12]
Didn't know that about 3D games.

Grey, in your Oz game do you only use timing code in windowed mode 'cause I noticed it runs at 60 Hz in fullscreen mode so I'm guessing no timing code in fullscreen?


Sean Doherty(Posted 2007) [#13]
Grey, do you use the integrate part of the time stepping?


Grey Alien(Posted 2007) [#14]
CGV: Basically most 3D games aren't VSynced so the time from one frame to the other can vary a lot and stuff like delta timing.tweening is used to work out how to update it. If the game loses time due to a background task, you'll just run a tiny bit further forward from one frame to the next frame but the correct amount relative to time so it's not that noticeable compared to say a smooth moving object in a 2D game - that's what I think anyway.

In Oz full screen DOES use timing, the same timing code as in windowed mode which is why it runs the same speed in both modes even though the screen Hz is different.

Sean: Yeah but I interpreted it in my own way by using a delta time on the last iteration of the loop.


Gabriel(Posted 2007) [#15]
I guess you're referring only to 2d games created with Max2D then, because I get silky-smooth performance with HGE in BlitzMax, even with hundreds of things bounding about the screen. Mind you, I get silky-smooth performance with 3d-accelerated 2d games made in B3D too. Well, I do with the good ones, not if they don't have good timing, obviously.


Grey Alien(Posted 2007) [#16]
hmm the plot thickens


Czar Flavius(Posted 2007) [#17]
Interesting tool Grey Alien. How does it work? I notice the most jerks with harddrive activity. It would be more useful if it was not full screen so I could do things and observe their impact. Also the file size is quite large. Using upx I can get it to 500kb, and it could be lower if you selected frameworks.


Sean Doherty(Posted 2007) [#18]
There is a lot of talk about the fact the integrating seems to keep flickering to minimum? Can someone explain how to go about implementing?

Thanks


Grey Alien(Posted 2007) [#19]
Czar Flavius: It's just this code:

'SetGraphicsDriver GLMax2DDriver()
Graphics 800,600,32
'Graphics 800,600,0

Local t1:Int
Local t2:Int
Local test: Int
Local high: Int
Local lo:Int = 200
Const MAXVALUES=800
Local values:Int[MAXVALUES]
Local counter=0
Local loops = 0
Local average = 0
Local total = 0

While Not KeyHit(KEY_ESCAPE)
	t1=MilliSecs()
	Cls
	DrawText "Current: "+test,0,0
	DrawText "High:    "+high,0,20
	DrawText "Low:     "+lo,0,40
	DrawText "Average: "+average,0,60
	DrawText "Press <Space> to reset High",0,80
	DrawText "Press <Escape> to exit",0,100
'	DrawText GCMemAlloced(),0,80
	For Local i=0 To MAXVALUES-2
		SetColor 255,255,0
		DrawLine 0,500,800,500
		SetColor 255,255,255
		DrawLine i,500-values[i],(i+1),500-values[i+1]
	Next
    Flip 1	
	t2 = MilliSecs() 
	test:Int = (t2-t1) 
	If test>high Then high = test
	If test<lo Then lo = test
	If KeyHit(KEY_SPACE) 
		high = 0
		lo = 200
		loops = 0
		average = 0
		total = 0
	End If
	values[counter] = test
	Counter:+1
	If counter>=MAXVALUES Then counter = 0
	loops :+ 1
	total :+ test
	average = total/loops
Wend


It measures the time in millisecs between each flip and plots it. You can change it windowed mode easily.


HrdNutz(Posted 2007) [#20]
Smooth animation and jitter-less timing can be tricky sometimes. It's true - background processes will make your time jitter - and that's where the problem comes from.

First step is obviously trying to fix the jitters. There are a few techniques, but averaging out the delta times is probably the simplest one.

Even fixed step loops use some type of Delta Timing as a base, to ensure the right amount of steps/second is executed. And the Delta Time is where jitters occur. The simple way to average Deltas is to keep adding new deltas to a buffer (removing the oldest ones) and using the average of all those as Delta Time. The buffer can scale dynamically depending on execution rate - a .5 second to 1 second buffer works well. There are other ways to do this, but this is the simplest and effective.

Linear interpolation for motion is also recommended (tweening), logic execution frequencies can stay low (15,30,60Hz) and motion is silky smooth, but this requires some ahead planning, and everything will have to be interpolated (positions, scales, angles, colors, ect...)

Tweening also ensures that any unused time gets translated to the next frame, independent of code frequency.

AltTabbing and Window moving can be tricky, if there is a way to know when either the application is not if focus (paused) or window being dragged, then that time can be recorded and simply subtracted from execution time so Deltas stay the same. Also, any deltas <=0 or larger than say 100ms can be completely rejected.
Hope this helps getting your game to run smoothly.


Grey Alien(Posted 2007) [#21]
great advice


SLotman(Posted 2007) [#22]
To know if your window has the focus, just use GetActiveWindow() from Windows API. if it returns a hwnd that's not the one in your program, then you don't have the focus.

Works great to "auto-pause" a game when the window looses focus ;)


TartanTangerine (was Indiepath)(Posted 2007) [#23]
Also, any deltas <=0 or larger than say 100ms can be completely rejected.
Like he said, if the delta is too large then ignore it and use the one from the frame before.

To know if your window has the focus, just use GetActiveWindow() from Windows API. if it returns a hwnd that's not the one in your program, then you don't have the focus.
You might consider using the GetFocus() command since it is possible for a window to be Active and not have focus.


Grey Alien(Posted 2007) [#24]
You might consider using the GetFocus() command since it is possible for a window to be Active and not have focus.
Hmm never knew that.


Russell(Posted 2007) [#25]
It's too bad that Windows isn't like AmigaOS in the sense that your game can completely takeover the system while it's running (I think there's a seldom used Windows API function called 'CriticalCodeFollows()' or something like that. Not sure if it does the same thing) and then return control back to the OS when it's done. What do you need background tasks for anyways when you're playing a fullscreen FPS? It'd be nice if you could at least force Windows into 'safe mode' before running your game, eh? This would at least reduce the amount of nonessential crappola running in the background and stealing cycles...

Russell


Grey Alien(Posted 2007) [#26]
Yeah I'd love it too. But I guess you couldn't collect emails or download something in the background.


HrdNutz(Posted 2007) [#27]
How about teamspeak or vent while playing? what about custom trainers you wrote to hack Diablo 2? :P

Consoles are as good as it gets with that, but then again they aren't as flexible either. Can alt+tab and chat in IRC/icq, download stuff in the backgrond, and have custom playlist in winamp

O.O

Cheers,
Dima


.rIKmAN.(Posted 2007) [#28]
Just ran that tool, got a low of 5 and a high of 33, and tht was with this window open, chatting to 1 person on MSN and running media player with about 12 tracks in the playlist.

All games run smooth on my system, and I play most of them in 1920x1080 (PES6, Stalker, Toca3 etc).

System: P4 3ghz, 1Gb DDR400, XFX7950GT 512mb Gfx card....

I haven`t actually tried many BMax stuff so can`t comment if it is limited to just those games or not...


Grey Alien(Posted 2007) [#29]
Are they all 3D games? Probably your system would be pretty smooth anyway, your highs and lows are pretty stable.


.rIKmAN.(Posted 2007) [#30]
Yeah those 3 I mentioned are commercial 3D games, if you wanna give me a list of some BMax stuff to try I`ll happily do it and report my results back.

If they are juddery tho, it has to be something to do with BMax as those other (resource heavy) games work flawlessly with all settings maxed out.


Grey Alien(Posted 2007) [#31]
I think I said before that timing jerks on 3D games don't show up as obviously as 2D games with a sprite moving at a constant speed or a screen scrolling for example.


watusimoto(Posted 2007) [#32]
I am dealing with jerkiness on a game I am working on that uses my own timing routines. The code is pretty minimal at this point, and if it's jerky now, I'm worried about it getting worse as things get more complex.

I don't know if it's a Blitz specific problem or not, but I suspect so. I was wondering if someone could code the jerktester in C++ or somesuch, and see how its performance compares. I think that would be a very interesting comparison.

Is anyone up for it?

Thanks much!!


Grey Alien(Posted 2007) [#33]
Yeah I had thought the same, or at least in BlitzPlus which uses DirectX1 or something whereas BMax uses DirectX 7.


MGE(Posted 2007) [#34]
I've done extensive testing on several Blitzmax games, demos, on several test machines. In full screen mode I don't notice anything out of the ordinary, but in windowed mode BMax apps do seem to "suffer the stutter" a tad bit more.


Grey Alien(Posted 2007) [#35]
The stutter exists in full screen mode on plenty of PCs too.


watusimoto(Posted 2007) [#36]
Well, let me ask this -- why would BM progs be any more or less stuttery than another app? At the end of the day, don't they all compile down to binaries that compete for system resources on the same level?


FlameDuck(Posted 2007) [#37]
What do you need background tasks for anyways when you're playing a fullscreen FPS?
So that when it crashes (which it will inevitably do) you can recover your system cleanly.


watusimoto(Posted 2007) [#38]
Well, here's something interesting. On a hunch, I inserted a timer into the JerkTester code posted above. My idea was that the jerkiness was caused by the program competing for resources with the rest of the system, and that we might see better results if the program shared a little better. (I basically inserted the waitTimer line, and also changed the flip 1 to flip 0) The result was that I see many fewer jerks with the modified code. Which is this:

SetGraphicsDriver GLMax2DDriver()
'Graphics 800,600,32
Graphics 800,600,0

Local t1:Int
Local t2:Int
Local test: Int
Local high: Int
Local lo:Int = 200
Const MAXVALUES=800
Local values:Int[MAXVALUES]
Local counter=0
Local loops = 0
Local average = 0
Local total = 0

local timer:tTimer=createTimer(100)

While Not KeyHit(KEY_ESCAPE)
	t1=MilliSecs()
	Cls
	DrawText "Current: "+test,0,0
	DrawText "High:    "+high,0,20
	DrawText "Low:     "+lo,0,40
	DrawText "Average: "+average,0,60
	DrawText "Press <Space> to reset High",0,80
	DrawText "Press <Escape> to exit",0,100
'	DrawText GCMemAlloced(),0,80
	For Local i=0 To MAXVALUES-2
		SetColor 255,255,0
		DrawLine 0,500,800,500
		SetColor 255,255,255
		DrawLine i,500-values[i],(i+1),500-values[i+1]
	Next
    Flip 0
    waitTimer(timer)
	t2 = MilliSecs() 
	test:Int = (t2-t1) 
	If test>high Then high = test
	If test<lo Then lo = test
	If KeyHit(KEY_SPACE) 
		high = 0
		lo = 200
		loops = 0
		average = 0
		total = 0
	End If
	values[counter] = test
	Counter:+1
	If counter>=MAXVALUES Then counter = 0
	loops :+ 1
	total :+ test
	average = total/loops
Wend



Grey Alien(Posted 2007) [#39]
The thing is really games need to run with Flip 1 for smoothness and no vertical tearing. I tried fiving time to the system as well, even raiing the app priority in windows but it didn't work on plenty of PCs.


watusimoto(Posted 2007) [#40]
So what's the resolution? It seems the most fundamental question is whether this is a Blitz-specific problem, or whether this is a problem common to all development environments. If it's Blitz-specific, the next question is why, and what can be done about it?

One thought I had was that with the "flip 1" statement, the system is not yielding control to Windows while it waits to do the flip, causing Windows to take control at other, less opportune times. Maybe there is a way to let the OS do its stuff while waiting for the flip to occur, which would let the game proceed more smoothly.


Grey Alien(Posted 2007) [#41]
Yes it could be that for sure, it could also be DX7. Really we need a very simple jerk tester code that can be compared in BMax, BPlus and C++ and maybe something else.