Seite 1 von 2

Danilos Highres-Timer-Procedure

Verfasst: 13.12.2004 16:03
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()

Re: Danilos Timer-Porcedure

Verfasst: 13.12.2004 16:18
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.

Verfasst: 13.12.2004 16:47
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.

Verfasst: 13.12.2004 17:01
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... ;)

Verfasst: 13.12.2004 17:18
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?

Verfasst: 13.12.2004 17:39
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.

Verfasst: 13.12.2004 18:35
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).

Verfasst: 13.12.2004 18:38
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.

Verfasst: 13.12.2004 19:04
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.

Verfasst: 13.12.2004 19:17
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