Framerate berechnen?

Für allgemeine Fragen zur Programmierung mit PureBasic.
Benutzeravatar
Mijikai
Beiträge: 754
Registriert: 25.09.2016 01:42

Framerate berechnen?

Beitrag von Mijikai »

Ist der Code richtig so ?

Code: Alles auswählen


;In WindowCreate

If QueryPerformanceFrequency_(@*GDI\Performance\Frequency)
  If QueryPerformanceCounter_(@*GDI\Performance\TimeStart)
    ;...
    
    
;In #WM_PAINT - Render Cycle!

*GDI\Performance\Count + 1
If *GDI\Performance\Count > 1000 ;1000 Zyklen warten -> Genauigkeit
  *GDI\Performance\Count = 0 ;Counter zurücksetzen
  If QueryPerformanceCounter_(@*GDI\Performance\TimeStop)
    *GDI\Performance\Framerate = (1000 / ((*GDI\Performance\TimeStop - *GDI\Performance\TimeStart) / *GDI\Performance\Frequency)) ;FPS berechnen !?
    QueryPerformanceCounter_(@*GDI\Performance\TimeStart)
  EndIf
EndIf

Debug "FPS: " + StrF(*GDI\Performance\Framerate)
Vielleicht ist es nur zu spät :coderselixir:
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8675
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 32 GB DDR4-3200
Ubuntu 22.04.3 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken
Kontaktdaten:

Re: Framerate berechnen?

Beitrag von NicTheQuick »

Wieso nutzt du nicht einfach ElapsedMilliseconds()?
Bild
Benutzeravatar
Kirito
Beiträge: 11
Registriert: 23.01.2018 13:54

Re: Framerate berechnen?

Beitrag von Kirito »

Code: Alles auswählen

Structure _FPS
  Counter.l
  Timer.l
  FPS.l
EndStructure 

Global FPS._FPS

Procedure GetFPS()
  
  If FPS\Timer + 1000 < ElapsedMilliseconds()
    FPS\FPS = FPS\Counter  
    FPS\Timer = ElapsedMilliseconds()
    FPS\Counter = 0
  Else 
    FPS\Counter + 1
  EndIf 
  
  ProcedureReturn FPS\FPS
EndProcedure 

OpenConsole("FPS")

Repeat 
  Delay(Random(100))
  PrintN("FPS: "+Str(GetFPS()))
ForEver 
Mfg,
Kirito
~ Lately, there are days I can’t even remember the other world.
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8675
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 32 GB DDR4-3200
Ubuntu 22.04.3 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken
Kontaktdaten:

Re: Framerate berechnen?

Beitrag von NicTheQuick »

Ich hätte noch das hier anzubieten. Die LinkedList ist nicht das schönste, aber die Implementierung eines Rolling Average ist für FPS einfach super geeignet.
Die Konstante #averaging gibt an über welchen Zeitraum der Durchschnitt berechnet werden soll.

Code: Alles auswählen

#averaging = 1000
Procedure.d getFPS()
	Protected now.q = ElapsedMilliseconds(), diff.i = 0
	Protected fps.d
	Static NewList frames.i()
	Static sum.i = 0, lastNow.q = -1
	
	If sum > #averaging
		If FirstElement(frames())
			sum - frames()
			DeleteElement(frames())
		EndIf
	EndIf
	diff = now - lastNow
	If lastNow >= 0 
		LastElement(frames())
		
		If AddElement(frames())
			frames() = diff
			sum + diff
		EndIf
	EndIf
	
	lastNow = now
	
	If sum = 0
		ProcedureReturn 0.0
	Else
		ProcedureReturn ListSize(frames()) * 1000.0 / sum
	EndIf
EndProcedure

Repeat
	Delay(1500)
	Debug "FPS: " + StrD(getFPS())
ForEver
Bild
Benutzeravatar
Imhotheb
Beiträge: 192
Registriert: 10.10.2014 13:14
Computerausstattung: Intel 8086, 640 KB RAM, Hercules Video Adapter, 2 x 5 1/4" 360kb Floppy, MS-DOS 3
Wohnort: Wolfenbüttel

Re: Framerate berechnen?

Beitrag von Imhotheb »

Dann auch noch eine Lösung mit einem Array ...

Code: Alles auswählen

Procedure.f FPS(Calc = #True)			; Calc = #False um den letzten Wert auszulesen ohne neu zu berechnen
  #ProcInternal_Max_FPS_Count = 5
  Static Dim FPS_Array(#ProcInternal_Max_FPS_Count)
  Static Count, Ticks, lastTime
  Static ret.f = 0
  Protected i, Time
  
  
  ; ===== Prevent low FPS at start =====
;   If lastTime = 0
;     For i = 0 To #ProcInternal_Max_FPS_Count
;       FPS_Array(i) = 60
;     Next
;   EndIf
  
  
  ; ===== Calc FPS =====
  If Calc
  	
  	Ticks + 1
  	Time = ElapsedMilliseconds()  
  	If Time - lastTime > 999
  		FPS_Array(Count) = Ticks
  		Ticks = 0
  		lastTime = Time
  		Count + 1
  		If Count > #ProcInternal_Max_FPS_Count
  			Count = 0
  		EndIf
  	EndIf
  	
  	
  	; Durchschnitt der letzten FPS (#ProcInternal_Max_FPS_Count + 1)
  	ret = 0
  	For i = 0 To #ProcInternal_Max_FPS_Count
  		ret + FPS_Array(i)
  	Next
  	ret = ret / (#ProcInternal_Max_FPS_Count + 1)
  	
  EndIf
  
  ProcedureReturn ret  
EndProcedure 


; ----- Beispiel -----
If InitSprite()
	If OpenWindow(0, 0, 0, 320, 200, "FPS-Test", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
		If OpenWindowedScreen(WindowID(0), 0, 0, 320, 200)
			
			Repeat
				StartDrawing(ScreenOutput())
				DrawText(0, 0, StrF(FPS(), 2))
				StopDrawing()
				FlipBuffers()
			Until WindowEvent() = #PB_Event_CloseWindow
			
		EndIf
	EndIf
EndIf
weil einfach einfach einfach ist ... mach' ich es anders
Antworten