Danilos Highres-Timer-Procedure

Für allgemeine Fragen zur Programmierung mit PureBasic.
Benutzeravatar
Lebostein
Beiträge: 674
Registriert: 13.09.2004 11:31
Wohnort: Erzgebirge

Danilos Highres-Timer-Procedure

Beitrag von Lebostein »

Ich hab aus dem alten Forum die Timer()-Routine von Danilo nochmal herausgekramt. Diese Routine scheint mir für eine zeitbasierte Spielsteuerung sehr gut zu funktionieren (besser als ElapsedMilliseconds). Mein Spiel läuft damit plötzlich viel flüssiger. :D

Meine Frage (@Danilo): Was genau wird denn in InitGameTimer() gemacht bzw. warum läuft mein Spiel damit so flüssig und wo genau ist der Unterschied zu den anderen Methoden ElapsedMilliseconds() und GetTickCount_()?

Code: Alles auswählen

Procedure InitGameTimer() 
  Shared _GT_DevCaps.TIMECAPS 
  SetPriorityClass_(GetCurrentProcess_(),#HIGH_PRIORITY_CLASS) 
  timeGetDevCaps_(_GT_DevCaps,SizeOf(TIMECAPS)) 
  timeBeginPeriod_(_GT_DevCaps\wPeriodMin) 
EndProcedure 

Procedure StopGameTimer() 
  Shared _GT_DevCaps.TIMECAPS 
  timeEndPeriod_(_GT_DevCaps\wPeriodMin) 
EndProcedure

InitGameTimer() 

Debug timeGetTime_()
Debug ElapsedMilliseconds()
Debug GetTickCount_()

StopGameTimer()
Zuletzt geändert von Lebostein am 13.12.2004 17:12, insgesamt 1-mal geändert.
Benutzeravatar
Danilo
-= Anfänger =-
Beiträge: 2284
Registriert: 29.08.2004 03:07

Re: Danilos Timer-Porcedure

Beitrag von Danilo »

Lebostein hat geschrieben:Meine Frage (@Danilo): Was genau wird denn in InitGameTimer() gemacht und wo genau ist der Unterschied zu den anderen Methoden ElapsedMilliseconds() und GetTickCount_()? Geht diese Form des Timers auf die Performance?
Die Prozedur InitGameTimer() setzt die Priorität des Prozesses
höher, also hat das Spiel dann vorrang vor anderen Prozessen.

Der wichtigere Teil kommt aber danach: Dort wird der Highres-Timer
von Windows auf den kleinstmöglichen Wert initialisiert, was in
der Regel 1ms ist. In der letzten Zeile wird gesagt das man
ab nun den genauen Timer benutzen möchte, was man dann
bei StopGameTimer() wieder zurücksetzen muß.

Die dazugehörige Funktion zur Abfrage ist dann timeGetTime_().

ElapsedMilliseconds scheint das nicht zu machen - genau kann
ich das aber nicht sagen.
ElapsedMilliseconds scheint aber irgendwie nicht genau zu
sein, und immer mal um ~5ms zu schwanken. Genau kann
das nur das PB-Team sagen, aber irgendwie kommt mir das
etwas ungenau vor.
cya,
...Danilo
"Ein Genie besteht zu 10% aus Inspiration und zu 90% aus Transpiration" - Max Planck
Benutzeravatar
Lebostein
Beiträge: 674
Registriert: 13.09.2004 11:31
Wohnort: Erzgebirge

Beitrag von Lebostein »

Ich hab mal folgendes ausprobiert:

Nach jedem Schleifendurchlauf meines Spieles hab ich mir den timeGetTime_()-Wert und den ElapsedMilliseconds()-Wert in ein Array speichern lassen. Dann hab ich für beide immer die Differenz zum vorhergehenden Zeitwert ausgerechnet, quasi die Zeit, die für einen Schleifendurchlauf erforderlich ist. Folgendes Ergebnis erhalte ich:

Code: Alles auswählen

#Loop  timeGetTime  ElapsedMilliseconds
01			7			16
02			5			0
03			6			0
04			6			15
05			6			0
06			6			0
07			6			16
08			6			0
09			5			15
10			6			0
11			6			0
12			6			16
13			6			0
14			6			0
15			7			16
16			5			0
17			6			15
18			6			0
19			6			0
20			6			16
21			6			0
...
...
...
Summe		125 ms	125 ms
Während ich mit timeGetTime_() eine fast konstante Zeit von 6 ms pro Schleifendurchlauf ausrechne, erhalte ich bei ElapsedMilliseconds() einen ziemlich abgehackten Verlauf. Teilweise scheint sich der Rückgabewert von ElapsedMilliseconds() auch nach einem vollständigen Schleifendurchlauf von 6 ms nicht zu ändern, so dass ich eine Zeitdifferenz von 0 ms ausrechne. Kein Wunder dass es so zum ruckeln kommt. Die absolute Zeit (aufsummiert) ist natürlich bei beiden gleich.
Benutzeravatar
Danilo
-= Anfänger =-
Beiträge: 2284
Registriert: 29.08.2004 03:07

Beitrag von Danilo »

Lebostein hat geschrieben:Teilweise scheint sich der Rückgabewert von ElapsedMilliseconds()
auch nach einem vollständigen Schleifendurchlauf von 6 ms
nicht zu ändern, so dass ich eine Zeitdifferenz von 0 ms
ausrechne. Kein Wunder dass es so zum ruckeln kommt.
Das ist genau diese Ungenauigkeit von der ich sprach, wodurch
ElapsedMilliseconds() ziemlich unbrauchbar ist.
Vielleicht möchtest Du diesen Test und meinen Code mal Fred
schicken, so daß er sieht wie man es richtig macht... ;)
cya,
...Danilo
"Ein Genie besteht zu 10% aus Inspiration und zu 90% aus Transpiration" - Max Planck
Benutzeravatar
Lebostein
Beiträge: 674
Registriert: 13.09.2004 11:31
Wohnort: Erzgebirge

Beitrag von Lebostein »

Hier mal ein simples Beispiel, mit dem man erkennt, das ElapsedMilliseconds() eine Auflösung von 15-16 ms hat und timeGetTime_() eine Auflösung von 1ms :allright:
(einfach die Befehle hinter "zeit =" austauschen)

Code: Alles auswählen

Procedure InitGameTimer() 
  Shared _GT_DevCaps.TIMECAPS 
  SetPriorityClass_(GetCurrentProcess_(),#HIGH_PRIORITY_CLASS) 
  timeGetDevCaps_(_GT_DevCaps,SizeOf(TIMECAPS)) 
  timeBeginPeriod_(_GT_DevCaps\wPeriodMin) 
EndProcedure

Procedure StopGameTimer() 
  Shared _GT_DevCaps.TIMECAPS 
  timeEndPeriod_(_GT_DevCaps\wPeriodMin) 
EndProcedure 

InitGameTimer()

Repeat
zeit = ElapsedMilliseconds() ;timeGetTime_()
If test <> zeit: Debug zeit - test: test = zeit: EndIf
ForEver
Was passiert, wenn ich den Timer mit StopGameTimer() nicht zurücksetze und mein Programm vorzeitig beende? Könnten beim weiteren Windowsbetrieb dann Probleme auftreten?
Benutzeravatar
Danilo
-= Anfänger =-
Beiträge: 2284
Registriert: 29.08.2004 03:07

Beitrag von Danilo »

Lebostein hat geschrieben:Was passiert, wenn ich den Timer mit StopGameTimer() nicht zurücksetze und mein Programm vorzeitig beende? Könnten beim weiteren Windowsbetrieb dann Probleme auftreten?
Normalerweise "sollte" nichts großartiges passieren.
Laut Doku (MSDN/PSDK) gehört zu jedem timeBeginPeriod_()
ein entsprechendes timeEndPeriod_().

Für *korrekte Programmierung* also wichtig - MS schreibt es
wohl nicht umsonst in die Doku. Auch wenn man selbst keine
Nebenwirkungen sieht, sollte man sich an die Doku halten und
es korrekt machen.
cya,
...Danilo
"Ein Genie besteht zu 10% aus Inspiration und zu 90% aus Transpiration" - Max Planck
GPI
Beiträge: 1511
Registriert: 29.08.2004 13:18
Kontaktdaten:

Beitrag von GPI »

Das ellipsedblabla() ungenau ist, wundert mich nicht. Der Aufruf wird vermutlich gettickcount_() aufrufen und der ist nicht genau (besonders bei kleine Zeiträume).
CodeArchiv Rebirth: Deutsches Forum Github Hilfe ist immer gern gesehen!
freak
PureBasic Team
Beiträge: 766
Registriert: 29.08.2004 00:20
Wohnort: Stuttgart

Beitrag von freak »

Danilo hat geschrieben:Das ist genau diese Ungenauigkeit von der ich sprach, wodurch
ElapsedMilliseconds() ziemlich unbrauchbar ist.
Vielleicht möchtest Du diesen Test und meinen Code mal Fred
schicken, so daß er sieht wie man es richtig macht... ;)
EllapsedMilliseconds ist nur ein wrapper zu GetTickCount_(), welches eben
nur so genau ist wie der system timer.

Das steht sogar so in der PB Hilfe.
Benutzeravatar
Danilo
-= Anfänger =-
Beiträge: 2284
Registriert: 29.08.2004 03:07

Beitrag von Danilo »

freak hat geschrieben:EllapsedMilliseconds ist nur ein wrapper zu GetTickCount_(), welches eben
nur so genau ist wie der system timer.

Das steht sogar so in der PB Hilfe.
Das heißt Du hältst es für unnötig es zu verbessern, und der
Programmierer muß mit dieser Ungenauigkeit leben?
Ist der Befehl dann auf allen von PB unterstützten Systemen
gleich ungenau/unbrauchbar?

Lebostein: Ich würde Dir trotzdem empfehlen diese Verbesserung
an Fantaisie Software weiterzugeben. Ich wüßte nicht wieso man dort
einen Vorschlag zur Verbesserung von PB ignorieren sollte.
cya,
...Danilo
"Ein Genie besteht zu 10% aus Inspiration und zu 90% aus Transpiration" - Max Planck
Benutzeravatar
Falko
Admin
Beiträge: 3535
Registriert: 29.08.2004 11:27
Computerausstattung: PC: MSI-Z590-GC; 32GB-DDR4, ICore9; 2TB M2 + 2x3TB-SATA2 HDD; Intel ICore9 @ 3600MHZ (Win11 Pro. 64-Bit),
Acer Aspire E15 (Win11 Home X64). Purebasic LTS 6.11b1
HP255G8 Notebook @AMD Ryzen 5 5500U with Radeon Graphics 2.10 GHz 3.4GHz, 32GB_RAM, 3TB_SSD (Win11 Pro 64-Bit)
Kontaktdaten:

Beitrag von Falko »

Danilo hat geschrieben:
freak hat geschrieben:EllapsedMilliseconds ist nur ein wrapper zu GetTickCount_(), welches eben
nur so genau ist wie der system timer.

Das steht sogar so in der PB Hilfe.
Das heißt Du hältst es für unnötig es zu verbessern, und der
Programmierer muß mit dieser Ungenauigkeit leben?
Ist der Befehl dann auf allen von PB unterstützten Systemen
gleich ungenau/unbrauchbar?

Lebostein: Ich würde Dir trotzdem empfehlen diese Verbesserung
an Fantaisie Software weiterzugeben. Ich wüßte nicht wieso man dort
einen Vorschlag zur Verbesserung von PB ignorieren sollte.
@FREAK
Die blöde Ausrede: Steht ja auch in der Hilfe.
Sorry du enttäuscht mich sehr. Warum wird Danilos Code nicht akzeptiert?
Ich würde mich viel lieber über ein optimiertes PB freuen.
Aber anscheinend will man das garnicht.
Sorry, das mußte mal sein, da man das Gefühl hat das solche und andere
Sachen wie z.B OGG-Sound etc. nicht wichtig genug seien. :allright:

MfG Falko
Bild
Win11 Pro 64-Bit, PB_6.11b1
Antworten