Frame limiting

BlitzMax Forums/BlitzMax Programming/Frame limiting

Tom(Posted 2005) [#1]
A search of the B'max forum isn't bringing up much, anyone have some nice frame limiting code?


TartanTangerine (was Indiepath)(Posted 2005) [#2]
I go with delta timing.I posted my code over at codersworkshop.


Tom(Posted 2005) [#3]
Got a link to it?

Cheers
Tom


TartanTangerine (was Indiepath)(Posted 2005) [#4]
Heh, I'll post it here




Type DeltaTime

	Global DeltaTList:TList

	Field OldTime:Double
	Field ElapsedTime:Double
	Field Delta:Double
	Field dFps:Double
	Field dDelta:Double
	Field CurrFps:Double
	Field FPSCounter:Double
	Field CurrTime:Double
	Field CheckTime:Double
	
		Method New ()
            	If DeltaTList = Null Then DeltaTList = New TList
            	DeltaTList.AddLast Self
    	End Method		
		
		Method Destroy ()
            	DeltaTList.Remove Self
        End Method

	
		Function Create:DeltaTime(Fps:Double)
			Local dTime:DeltaTime = New DeltaTime
			dTime.Delta = 1
			dTime.dFps = Fps
			dTime.dDelta = 1000/Fps
			Return dTime
		End Function
		
		Function Update()
			Local dTime:DeltaTime
			For dTime:DeltaTime = EachIn DeltaTList
				dTime.CurrTime = MilliSecs()
				dTime.ElapsedTime = dTime.CurrTime - dTime.OldTime
				dTime.OldTime = dTime.CurrTime
				
				If dTime.CurrTime > dTime.CheckTime
					dTime.CheckTime = dTime.CurrTime + 1000
					dTime.CurrFps = dTime.FPSCounter
					dTime.FPSCounter = 0
				Else
					dTime.FPSCounter:+1
				EndIf
			Next
			
		End Function
		
		Function FPS(dTime:DeltaTime)
			Return dTime.CurrFps
		End Function
		
		Function CurrDelta:Double(dTime:DeltaTime)
			Return dTime.ElapsedTime/dTime.dDelta
		End Function
		
End Type




Filax(Posted 2005) [#5]
Any chance to show how it work ?


Who was John Galt?(Posted 2005) [#6]
Tom - If I remember correctly, you are using 'ball physics' in one of your games - delta timing doesn't work well at all with these types of games - gives wildly different results on different machines and you will need a logic loop that executes at a fixed rate on all machines to make something reproducable.


TartanTangerine (was Indiepath)(Posted 2005) [#7]
Example:

Set Your Globals
Global Delta1:DeltaTime = DeltaTime.Create(35.0) ' Normal 35 FPS
Global Delta:Double


Now Main Game Loop
While Not EXIT_FLAG

	DeltaTime.Update()
	Delta = DeltaTime.CurrDelta(Delta1)
	If Delta > 1 Then Delta = 1 ' Delta should never be bigger than 1.
	
	' -------------------------------GFX FUNCTIONS ---------------------------
	ScreenUpdate = ScreenUpdate + Delta
	
	ScreenX.Update(Delta)
	
	If ScreenUpdate > 0.30 Then
		RenderGFX()
		ScreenUpdate = 0
		Timer.UpdateAll()
	EndIf	
	' ------------------------------------------------------------------------
	
	UpdateGame(delta)
	ActiveChannel.UpdateAll()	
	FlushMem
	Delay(1)
	
Wend


Multiply all movements and animations etc by Delta.


Filax(Posted 2005) [#8]
Many Thanks


Filax(Posted 2005) [#9]
Hi try to modify this code but it's strange the blob don't move ?




TartanTangerine (was Indiepath)(Posted 2005) [#10]
Ah okay, sorry you need to multiply the amount you want the object to move by Delta. Also you need to make your bx variable a double.

See below


TartanTangerine (was Indiepath)(Posted 2005) [#11]
In fact your code should really be this since you are not rendering the gfx every frame, only when screenupdate reaches a certain threshold. You need to pass screenupdate as the delta.




Filax(Posted 2005) [#12]
Ok !! thanks :) but i have a little question ? this piece of code
can be compared with tweening method ?

Because if i change :
Global Delta1:DeltaTime = DeltaTime.Create(35.0) ' Normal 35 FPS

With
Global Delta1:DeltaTime = DeltaTime.Create(10.0) ' Normal 10 FPS

The circle move more slowly ? it is normal ? If 'im remember
the blitz3d tweening method the object move in the same distance/time with more or less FPS ?


TartanTangerine (was Indiepath)(Posted 2005) [#13]
That command sets the Frame Rate, all delta time will be based off of that rate. Once you have set the rate all object movement will be exactly the same regardless of the speed or the machine it is running on.

To demonstrate this put a random delay in your loop and see what happens.

Delay Rand(1,20)



Tom(Posted 2005) [#14]
Nice code.

I've since come to realise that at certain FPS rates (when the drawing rate drops low) then things are gonna get juddery and there's nothin you can do about it really.

i.e, if the monitor refreshrate is 85 and the draw rate drops to 60 fps, then 25 of those 60 frames will be displayed twice during the monitors 85 refreshes. That's the problem I was having but not understanding til now.

Of course it's gonna be rare that drawing drops that low so it's not too big a deal after all.

Tom


TartanTangerine (was Indiepath)(Posted 2005) [#15]
Change this following line of code if you think the FPS is going to get lower than you set it. Example : If you set the FPS at 35 then change this to "2" then the FPS can go as low as 17.5 and things will run okay.
If Delta > 1 Then Delta = 1 ' Delta should never be bigger than 1.



Filax(Posted 2005) [#16]
Hi Videogame Takeaway

I have two questions :

- I'm obliged to use alway double value ? like this :
MySpritePX:Double=10

....
MySpritePX=MySpritePX+1*Delta
....

It is correct ?

- I don't understand very well the line :
If ScreenUpdate > 0.30 Then

Can you clarify ?

I notify a strange stuff :
when i want to know the FPS with : DrawTex DeltaTime.FPS(Delta1),10,10

This return some strange value between 60=>145698=>65=>300 etc ? when i open a screen with the NOSYNC flag, any idea ?
or i must use a constant refresh rate, like 60 ?

Cheers


TartanTangerine (was Indiepath)(Posted 2005) [#17]
Hi Filax,

Use floats or doubles, your choice but never Ints.

- I don't understand very well the line :
If ScreenUpdate > 0.30 Then

Based on the Frame Rate I set earlier in the code this line forces a screen update about every 60th of a second and prevents a screen update occuring every computational frame.

The FPS reported is actually the speed of each computational frame, remember graphics are only rendered when Screenupdate > 0.30

Does this help? probably not, I'm tired and full of beer. Ask me again if you need me to explain.

PS. Call me Tim.


Steve Elliott(Posted 2005) [#18]

PS. Call me Tim (not Videogame Takeaway).



Bring back Indiepath I say - know who you are then. ;-)


TartanTangerine (was Indiepath)(Posted 2005) [#19]
Na, that would be boring.


Filax(Posted 2005) [#20]
lol Tim :)))))))))))

Drink another beer for me :) i understand now :) thank !!!


Filax(Posted 2005) [#21]
Tim

The last question, it's a fault if use use a NOSYNC graphics screen ?


TartanTangerine (was Indiepath)(Posted 2005) [#22]
Please use NOSYNC, it allows the logic to update without waiting for the vSync Signal.

This is particularly good for physics applications where you need a fast logic update but only want to actually draw to screen when needed.


Filax(Posted 2005) [#23]
Oh, thank for reply :) but when i'm making a screen with
NOSYNC parameter the function Function FPS(dTime:DeltaTime)
return a strange number between 60=>1235718 ??

Try this :




SillyPutty(Posted 2005) [#24]
This is excellant code !! :) awome stuff :)

can I ask why you use a list for delta time type ?

Why would one need to add more delta time types into a list ? or is that only on "new"

Sorry for the noob questions.


TartanTangerine (was Indiepath)(Posted 2005) [#25]
Yes, I get that too. It's reporting the actual speed of the game loop and not the Amount of Renders Per Second. The reason being that we've told the application to only render to screen when the ScreenUpdate variable reaches a certain threshold, thus we already know what the maximum amount of rendered FPS will be. If the Rendered FPS dips below the ScreenUpdate threshold then it will be reported as Rendered FPS and not number of application loops per second.

If you take out the ScreenUpdate checks then you will get the REAL ACTUAL Rendered FPS.

Oh and I recently updated the Delta code, it's a lot more accurate now and faster :D


@Deux, I use this method as it's good OOP practice, it keeps everything nice and neat. I may also need multiple Delta Timers controlling different things - this code gives me the flexibility.


Filax(Posted 2005) [#26]
Hi Tim :)

Nice piece of code :) but i have another question (no ! don't
kill me !! PAN !)

What this method ?

Method SetFPS(NewFPS:Float)
Self.dFPS = NewFPS
Self.dDelta = 1000/Self.dFPS
End Method


TartanTangerine (was Indiepath)(Posted 2005) [#27]
Arrrgghhhhhh... LOL

This allows you to dynamically adjust the game timing.

For example, you initialise the timing with:-
Global Delta1:DeltaTime = DeltaTime.Create(35.0)

You code your game objects and animations based on that setting (35.0).

Now lets say you want to dynamically speed up or slow down the whole game. You can affect the whole game speed by setting the new FPS (maybe wrong name for function but who cares). I do this to great effect in GEOM, when you get a SLOWMO powerup the game speed is 50% of normal ie. SetFPS(NormalSpeed/2).

Cool eh?


TartanTangerine (was Indiepath)(Posted 2005) [#28]
One more thing....

You may like to know that I put the IGlass update command in the ScreenUpdate portion of code in my new application and it still works fine. The benefit being that IGLass updates are only done at each screen render and do not affect the game logic speeds at all.

	' -------------------------------GFX FUNCTIONS ---------------------------
	ScreenUpdate :+ Delta
	
	If ScreenUpdate > 0.5 Then
		ScreenUpdate :-0.5
		Parse_Render_States()
		IGL_RefreshGui()
	EndIf	
	
	' -------------------------------------------------------------------------



Filax(Posted 2005) [#29]
Ok ok !! very interesting !!! Many thanks to reply :)


Filax(Posted 2005) [#30]
I'm trying to make a little template for using simply your
delta code :

The template :


Here is the include : Inc_Delta.bmx


If you find some error tell me !

Cheers


TartanTangerine (was Indiepath)(Posted 2005) [#31]
Looks okay to me BUT I have not tested it.


tonyg(Posted 2005) [#32]
'Identifier destroy not found'
Should it be my_appdelta.destroy()
?


Filax(Posted 2005) [#33]
Tonyg it's ok now :)