Seite 2 von 2
Re: [GameLoop] DeltaTime & FPS ? (kein V-Sync/Framelimit)
Verfasst: 06.05.2018 18:55
von Mijikai
mk-soft hat geschrieben:Es ist besser mit Frames zu arbeiten um nicht die CPU Last zu hoch zu schrauben...
...
Danke, verwendet aber leider AddWindowTimer() was ich (später) nicht nutzen kann.
Der Code soll auch bei Fenstern funktionieren die nicht mit PureBasic erstellt wurden.
Hier mal mein Ansatz, leider ist noch was falsch es wird auf ~100 FPS
gedrosselt anstatt auf 60!
Code:
Code: Alles auswählen
DeclareModule FPS
Declare.i Init()
Declare.i Count()
Declare.f Delta()
Declare.i Update()
EndDeclareModule
Module FPS
#FPS_60 = 16
#FPS_30 = 33
#FPS_25 = 40
#FPS_80 = 12
#FPS_75 = 13
#FPS_24 = 41
#FPS_20 = 50
#FPS_10 = 100
Structure PERFORMANCE_STRUCT
FrameTarget.q
FrameStart.q
FrameEnd.q
FrameTime.f
Timing.f
FrameCount.i
FPS.i
DeltaTime.f
EndStructure
Global Performance.PERFORMANCE_STRUCT
Procedure.i Init()
With Performance
\FrameTarget = #FPS_60;GEWÜNSCHTE FPS!
\FrameStart = ElapsedMilliseconds()
EndWith
EndProcedure
Procedure.i Count()
ProcedureReturn Performance\FPS
EndProcedure
Procedure.f Delta()
ProcedureReturn Performance\DeltaTime
EndProcedure
Procedure.i Update()
With Performance
If \FrameTime < \FrameTarget
Delay(\FrameTarget - \FrameTime);NICHT KORREKT !?
EndIf
\FrameEnd = ElapsedMilliseconds()
\FrameTime = \FrameEnd - \FrameStart
\DeltaTime = \FrameTime / \FrameTarget
\FrameStart = \FrameEnd
If \Timing > 999
\FPS = \FrameCount
\Timing = 0
\FrameCount = 1
Else
\Timing + \FrameTime
\FrameCount + 1
EndIf
EndWith
EndProcedure
EndModule
If InitSprite()
If OpenWindow(0,0,0,400,400,"TestWindow",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
If OpenWindowedScreen(WindowID(0),0,0,400,400,#False,0,0,#PB_Screen_NoSynchronization);<- KEIN SYNCH!
FPS::Init()
Repeat
ClearScreen($EB8724)
If StartDrawing(ScreenOutput())
DrawingMode(#PB_2DDrawing_Transparent)
DrawText(10,10,"FPS: " + Str(FPS::Count()))
DrawText(10,30,"DLT: " + StrF(FPS::Delta(),2))
StopDrawing()
Else
PostEvent(#PB_Event_CloseWindow)
EndIf
FlipBuffers()
FPS::Update()
Until WindowEvent() = #PB_Event_CloseWindow
EndIf
EndIf
EndIf
Re: [GameLoop] DeltaTime & FPS ? (kein V-Sync/Framelimit)
Verfasst: 06.05.2018 19:00
von RSBasic
Achso, du verwendest OpenWindowedScreen. Dann ist ein Delay schon sinnvoll, um den Prozessor zu entlasten.
In der PB-Hilfe unter OpenWindowedScreen gibt es ein Beispielcode mit einem Delay(1) und die Screen-Anwendung verbraucht nur 1 %-Prozessorauslastung.
Re: [GameLoop] DeltaTime & FPS ? (kein V-Sync/Framelimit)
Verfasst: 06.05.2018 19:52
von ccode_new
Huhu!!!!
Es ist eigentlich recht simpel.
Wichtig ist eine konstante Framerate festzulegen und die Zeit zwischen dem Aktualisieren zu messen (DeltaT).
Das sind eigentlich die Standards und alles ist locker flockig handelbar.
Man sollte aber beachten das trotz NOSync meist Treibertechnisch trotzdem bei 60 FPS abgeriegelt wird.
Re: [GameLoop] DeltaTime & FPS ? (kein V-Sync/Framelimit)
Verfasst: 06.05.2018 21:38
von Jan125
Hm, keine Ahnung ob das weiterhelfen könnte, aber mal 'ne kleine Entkoppelung via Threads.
Vermutlich müssen sich die erfahreneren Coder hier gleich übergeben. ;P
Code: Alles auswählen
Procedure.l GetTime()
Static TimeLast.l
Protected TimeNow.l
Protected TimeReturn.l
If TimeLast = 0
TimeLast = ElapsedMilliseconds()
ProcedureReturn 0
EndIf
TimeNow = ElapsedMilliseconds()
TimeReturn = TimeNow-TimeLast
TimeLast = TimeNow
ProcedureReturn TimeReturn
EndProcedure
Procedure.l ThreadDelay(Delay)
Delay(Delay)
ProcedureReturn 0
EndProcedure
Structure ObjectStructure
EndStructure
Global Mutex.l
Global NewList svObjectList.ObjectStructure()
Global NewList clObjectList.ObjectStructure()
Procedure GameInit()
UsePNGImageDecoder()
InitSprite()
InitSound()
InitKeyboard()
PrintN("Opening window.")
OpenWindow(1, #PB_Ignore, #PB_Ignore, 800, 600, "asCL")
PrintN("Opening screen.")
OpenWindowedScreen(WindowID(1), 0, 0, 400, 300, 1, 0, 0, #PB_Screen_NoSynchronization)
TransparentSpriteColor(#PB_Default, $ff00ff)
For i = 0 To 0
AddElement(svObjectList())
Next
EndProcedure
Procedure GameClient()
Protected Event.l
;SetFrameRate(1000)
UnlockMutex(Mutex)
Repeat
Repeat
Event = WindowEvent()
Select Event
Case #PB_Event_CloseWindow
Quit = 1
EndSelect
Until Event = 0
ClearScreen($606060)
LockMutex(Mutex)
CopyList(svObjectList(), clObjectList())
UnlockMutex(Mutex)
ForEach clObjectList()
;;Display Objects
Next
FlipBuffers()
Until Quit = 1
ProcedureReturn 0
EndProcedure
Procedure GameServer(Rate_TickRate = 100) ;low overhead asynch rate server
Protected ThreadDelayID.l
Protected Correction.l
Protected Time.l
Protected ThreadCreationCorrection.l
For i = 1 To 10
Time = ElapsedMilliseconds()
ServerDelay = CreateThread(@ThreadDelay(), 1)
WaitThread(ServerDelay)
ThreadCreationCorrection+(Time-ElapsedMilliseconds())
Next
ThreadCreationCorrection/10
PrintN("Thread creation delay: "+Str(ThreadCreationCorrection))
Time = ElapsedMilliseconds()
Rate_Elapsed = Rate_TickRate
PrintN("Resuming server loop.")
Repeat
Correction = Correction+(Rate_TickRate-Rate_Elapsed)
If Rate_TickRate+Correction+ThreadCreationCorrection > 0
ServerDelay = CreateThread(@ThreadDelay(), Rate_TickRate+Correction+ThreadCreationCorrection)
EndIf
;;Debugger has to be disabled when calling Keyboard functions in a thread.
;;Else it will raise an exception
DisableDebugger
ExamineKeyboard()
LockMutex(Mutex)
FirstElement(svObjectList())
;;Keyboard Queries
EnableDebugger
ForEach svObjectList()
;;Object Actions
Next
UnlockMutex(Mutex)
WaitThread(ServerDelay)
Rate_Elapsed = ElapsedMilliseconds()-Time
Time+Rate_Elapsed
PrintN(Str(Rate_Elapsed))
Debug Correction
ForEver
ProcedureReturn 0
EndProcedure
If OpenLibrary(0, "Kernel32.dll")
Prototype GetConsoleWindow()
Define GetConsoleWindow.GetConsoleWindow = GetFunction(0, "GetConsoleWindow")
CloseLibrary(0)
EndIf
OpenConsole()
ConsoleHandle = GetConsoleWindow()
EnableMenuItem_(GetSystemMenu_(ConsoleHandle, #False), #SC_CLOSE, #MF_DISABLED)
Mutex = CreateMutex()
GameInit()
LockMutex(Mutex)
Server = CreateThread(@GameServer(), 20)
GameClient()
PrintN("Locking server thread.")
LockMutex(Mutex)
KillThread(Server)
PrintN("Killed server thread.")
UnlockMutex(Mutex)
PrintN("Shutting down.")
End
Müsstest eben was in die Struktur einfügen und auch Aktionen dafür festlegen...
Re: [GameLoop] DeltaTime & FPS ? (kein V-Sync/Framelimit)
Verfasst: 06.05.2018 21:49
von ccode_new
Ah!
"ThreadCreationCorrection"
Vermutlich müssen sich die erfahreneren Coder hier gleich übergeben. ;P
Keine Ahnung!
Re: [GameLoop] DeltaTime & FPS ? (kein V-Sync/Framelimit)
Verfasst: 06.05.2018 22:46
von Mijikai
Jan125 hat geschrieben:Hm, keine Ahnung ob das weiterhelfen könnte, aber mal 'ne
kleine Entkoppelung via Threads.
Vermutlich müssen sich die erfahreneren Coder hier gleich übergeben. ;P
Müsstest eben was in die Struktur einfügen und auch Aktionen dafür festlegen...
Was passiert hier ?
Ist zu komplex/durcheinander für mich.
Re: [GameLoop] DeltaTime & FPS ? (kein V-Sync/Framelimit)
Verfasst: 07.05.2018 06:33
von Jan125
Ups, stimmt ja...
Ich entkoppele die Logik von der Anzeige via Threads.
Der Großteil des Codes besteht aus Zeitstabilisierung und Korrektur (dazu eben noch das Thread-Erzeugungs-Delay, denn der Delay wird asynchron über einen weiteren Thread bewerkstelligt).
Im Endeffekt kümmert sich der "Server" um Eingaben und alles andere, packt darzustellende Objekte in eine Liste, der "Client" kopiert diese Liste und stellt sie dann dar.
Somit muss man sich um Frameratediskrepanzen keine Sorgen mehr machen. ^w^
(Das Ganze könnte dennoch nicht ganz Save sein, siehe Anmerkung zu Tastaturevents im Server.)
Re: [GameLoop] DeltaTime & FPS ? (kein V-Sync/Framelimit)
Verfasst: 08.05.2018 22:05
von Mijikai
Würde den Code gerne besser verstehen
- Wo ist die Procedure -> ThreadDelay() ?
Code: Alles auswählen
CreateThread(@ThreadDelay(), 1)
;...
CreateThread(@ThreadDelay(), Rate_TickRate+Correction+ThreadCreationCorrection)
;...
- Wird WindowEvent() nicht geblockt solange bis es ein Signal gibt ?
- Der Code scheint den Prozessor nicht zu entlasten hängt bei mir bei 5 - 8% !
Re: [GameLoop] DeltaTime & FPS ? (kein V-Sync/Framelimit)
Verfasst: 09.05.2018 05:17
von Jan125
ThreadDelay ist ganz oben, zweite Prozedur.
Soll einfach nur als Zeitgeber fungieren.
Nö, das wäre WaitWindowEvent, und wenn man das benutzen würde, dann würde die Darstellung blockieren.
(Oder man macht einen weiteren Thread...)
Entlastung ist hier nicht das Ziel, die Performance wird sogar eher stark abnehmen. Hier soll nur die Tickrate korrigiert werden (wenn in einem Tick zu viel bearbeitet werden muss kann das durch den nächsten Tick u. U. ausgeglichen werden), sowie eine generelle Unabhängigkeit von der britischen Kron-... Äh, von der Bildwiederholfrequenz des Monitors (ältere CRTs haben z. B. meist 75Hz statt 60Hz, manche neueren Monitore 144Hz).
Da ich morgen frei habe setz' ich mich heute Abend mal hin und schreib 'n kleines Beispiel. :>
Re: [GameLoop] DeltaTime & FPS ? (kein V-Sync/Framelimit)
Verfasst: 09.05.2018 23:30
von Mijikai
Jan125 hat geschrieben:ThreadDelay ist ganz oben, zweite Prozedur.
Soll einfach nur als Zeitgeber fungieren.
Ah, das habe ich tatsächlich nicht gesehen, sah wie eine Funktion aus.
Jan125 hat geschrieben:Nö, das wäre WaitWindowEvent, und wenn man das benutzen würde, dann würde die Darstellung blockieren.
(Oder man macht einen weiteren Thread...)
Ok das ist gut, ich steig bei Threads noch nicht wirklich durch.
_________________________________________________________________________________________
Ich hab bei meinem Code jetzt eine 'Clock' hinzugefügt um ein Render-Event auszulösen.
Damit funktioniert es jetzt.
Momentan wird der Prozessor mit Delay(1) entlasted, besser
wäre ein Nano-Sleep (möglich aber nur mit OS-API).