Frames Per Second Ticker...

Blitz3D Forums/Blitz3D Beginners Area/Frames Per Second Ticker...

Sharlenwar(Posted 2006) [#1]
Okay, I've been searching for some sort of a code example for getting the FPS, but I can't seem to find one. I just got Blitz3D yesterday and I love it.

Any help is appreciated, even just a point in the right direction will help.

Thanks!


Sharlenwar(Posted 2006) [#2]
Well I sorta figured it out. I made a function as follows:
Function ExtractFPS()
     frame=frame+1
     If MilliSecs() > time Then
          time = MilliSecs()+1000
          fps = frames
          frame = 0
     EndIf
     Return fps
End Function


It seems to work. If I've bugged it up, let me know.


Matty(Posted 2006) [#3]
Unless you have specified 'time' as a global variable it will always reset to zero as it is local to the function you have created. If you put this in your main loop it would work instead of as a function.


Bobysait(Posted 2006) [#4]
Use this one => no need Globals


type Fps_Counter
 field FpsT%
 field FpsCur%
 field FpsRate%
end type

function FPS_GetFps(Time%)
 fps.FPS_Counter=last FPS_Counter
 if fps=null fps.FPS_Counter=new FPS_Counter
 if time>fps\FpsT
  fps\FpsT=Time+1000
  fps\FpsRate=fps\FpsCur
  fps\FpsCur=0
 else
  fps\FpsCur=fps\FpsCur+1
 endif
 return fps\FpsRate
end function


You 'll just have to mention the current Time
=> Fps=FPS_GetFps( millisecs() )

It "autodetects" if the type already exists or not ( if not, it creates a new one )

It 's radically faster than using globales !


Sharlenwar(Posted 2006) [#5]
Okay interesting, thanks!


DH(Posted 2006) [#6]
This should give you a nice average of FPS rather than some crazy number thats always changing and hard to read. This is using a bit of Bobysait's technique (single function call):
Type objFPS
	Field Array[129]
	Field Total
	Field Index
	Field LastTime
	Field LastIndex
End Type

Function GetFPS()
	Local This.objFPS, ThisTime#
	This						=First objFPS
	If This = Null Then 
		This = New objFPS 
		This\Index 					=0
		This\LastIndex 				=1
	EndIf
	This\Index 					=(This\Index  Shr 0 And 127 Shl 0) + 1
	This\LastIndex 				=(This\LastIndex  Shr 0 And 127 Shl 0) + 1
	This\Array[This\Index]		=MilliSecs() - This\LastTime 
	This\LastTime 				=MilliSecs()
	This\Total 					=This\Total + This\Array[This\Index] - This\Array[This\LastIndex]
	ThisTime#					=Float(This\Total) / 128.0
	If ThisTime = 0 Then
		Return(1000)
	Else
		Return(1000.0 / ThisTime)
	EndIf
End Function


You could make this one bit faster by creating your type first and passing it into the function (so the function doesn't have to check to see if one exists).


Bobysait(Posted 2006) [#7]
As you call the function only once a loop, it's not really a loss for performance. => and, Types are very fast, so maybe calling a function with argument won't be faster.

For noobs, function without initialisation is better. So they prefer when there is no need to create anything around the function.

ps : I'm trying to understand your code... strange way to get the fps. But it seems to be a good way !


DH(Posted 2006) [#8]
Well, its getting an average. The reason I wrote it that way is because to get an average you need to add alot of 'samples' and then divide by the number of samples. Instead of looping through all the samples and adding each one, I just add it to a total sample, and minus the oldest sample from the total, and then divide that by total samples (128). Reason for doing bit shifting and masking on the + 1 is because I need to bring the index around to 1 when it gets to the max number of samples. Quicker for the compiler to make this code (the constant shifting) super fast rather than have to do an if->then jump in the code (thus doing a comparrison, and a jump, where as I am just doing a bitshift which comes around at 128 anyhow).

This is the quickest way I could find to get an average fps. Reason I needed the quickest way is because I wanted to find the absolute bottlenecks in my code (average timers), and looping through to get samples and add them all each loop kinda eats up ticks.. :-)


markcw(Posted 2006) [#9]
this is my personal favorite because it's short.

 ;fps counter
 If MilliSecs()-settime>1000
  getfps=setfps : setfps=0 : settime=MilliSecs()
 Else
  setfps=setfps+1
 EndIf

 Text 0,0,"FPS="+getfps



Bobysait(Posted 2006) [#10]
@Dark Half : Ok, thanks for explain. your function roxx !