Millisecs() - Timer

Übersicht BlitzBasic FAQ und Tutorials

Neue Antwort erstellen

BladeRunner

Moderator

Betreff: Millisecs() - Timer

BeitragSo, Jul 03, 2005 13:57
Antworten mit Zitat
Benutzer-Profile anzeigen
Da es immer wieder gefragt wird und somit sicher von Interesse ist, in aller Kürze ein Minitut über Millisecs-Timer.

Wofür ?
Alle Prozesse in Euren Programmen die zeitkritisch ablaufen und wiederkehrend ablaufen, also zB Animationen oder ein Countdown.

Weshalb ?
Die Timerbefehle von BB und auch Delay haben einen gravierenden Nachteil: Das Programm wird bis zum nächsten Timerklick bzw. bis zum Ablaufen der Delayzeit komplett angehalten. Erstens geht einem dadurch wertvolle Rechenzeit verloren (zumindest bei grösseren Projekten unverzeihlich), zum anderen ist es kaum möglich bzw. sehr schwer, verschieden schnell ablaufende Prozesse gleichzeitig zu realisieren. Der Millisecs()-Timer umgeht diese Problematik. Jeder Prozess erhält seinen eigenen Takt und das Programm wird nicht angehalten (und somit ausgebremst).

Wie ?
Eigentlich ist es gar nicht schwer. Erstmal zur Theorie. Man setzt einen Startzeitpunkt. Bei jedem Schleifendurchlauf schaut man nun nach ob die aktuelle Systemzeit grösser ist als eben dieser Startzeitpunkt plus die gewünschte Verzögerung. Sollte dies der fall sein, führt man aus, was man im Intervall machen möchte (z.B. Framecounter erhöhen, Variabeln setzen etc.) und setzt den Startzeitpunkt auf die aktuelle Systemzeit.
Der Vorteil an dieser Methode liegt auch darin dass der erste Start automatisch erfolgt, auch wenn die Startzeitpunkt-Variable noch nicht belegt wurde, da sie dann ja mit einer "0" befüllt ist und somit auf jeden Fall kleiner ist als die Zeit in Millisecs().

Vorsicht: Bislang hat unser Timer noch einen kleinen, aber dennoch gravierenden Nachteil. Die Systemzeit wird in einer vorzeichenbehafteten Integer gespeichert. Wenn der Rechner nur lange genug läuft erreicht Millisecs() das Vorzeichenbit, und ab dann ist das Ergebnis "negativ", d.h. Millisecs liefert Zahlen <0 zurück. Dann würde unser Timer nicht mehr funktionieren. Nur die wenigsten Leute haben ihren Rechner so lange an, dennoch will man ja alle Anwender zufriedenstellen. Die Lösung für dieses Problem ist auch denkbar einfach: Wir maskieren mit AND einfach das Vorzeichenbit von Millisecs und unser Timer bleibt immer positiv Wink
Aber genug der Theorie, hier kommt Code:
BlitzBasic: [AUSKLAPPEN]

SetBuffer BackBuffer() ; immer Doublebuffern

startzeit= (MilliSecs() And $7fFFffFF) ; initialisieren der Startzeit. Nicht nötig, aber zeugt von gutem Stil.
; Man beachte dass das Vorzeichenbit maskiert wird, um bei langlaufenden Rechnern
; eine Timerfunktion zu gewährleisten.

Const DAUER = 150 ; die Dauer eines einzelnen Durchlaufes. Kann auch non-konstant sein und könnte auch
; direkt in der Abfrage stehen.

; Mainloop

Repeat

Zeit = (MilliSecs() And $7fFFffFF) ; Die aktuelle Zeit wird abgenommen. Bei einem einzelnen Timer kann man sich
; das Speichern in einer Variablen sparen, bei mehreren ist es jedoch schneller
; immer gegen die Variable zu prüfen als immer Millisecs() aufzurufen.

If zeit >= startzeit + DAUER Then ; ist die Zeit für einen Durchlauf erreicht ?
startzeit = (MilliSecs() And $7fFFffFF) ; dann wird die Startzeit neu festgelegt....
Text Rand(200),Rand(200),\"Blitz!!!!\" ; und ausgeführt was auszuführen ist. Hier nur ein unsinniges Beispiel.
EndIf ; c´est ca. der Timer steht.

Flip
Cls

Until KeyHit(1) ; Beenden mit ESC.
End


Jeder weitere Timer muss nur mit einer eigenen Startzeitvariablen und Dauer versehen werden, und es sind unabhängige Prozesse möglich. Es wäre bei mehreren Timern also zum Vermeiden von Variablenwust ratsam sie in einem Dim zusammenzufassen.

So, That´s it, folks.

Viel Spass mit euren Timern Wink

EDIT: Leider wird die Formatierung bei BB-code etwas zerstückelt, ich hoffe es ist dennoch lesbar.
Zu Diensten, Bürger.
Intel T2300, 2.5GB DDR 533, Mobility Radeon X1600 Win XP Home SP3
Intel T8400, 4GB DDR3, Nvidia GF9700M GTS Win 7/64
B3D BMax MaxGUI

Stolzer Gewinner des BAC#48, #52 & #92

Lunatix

BeitragSo, Jul 03, 2005 14:04
Antworten mit Zitat
Benutzer-Profile anzeigen
Schon mal net schlecht erklärt nur das versteh ich net :

BlitzBasic: [AUSKLAPPEN]
startzeit = (MilliSecs() And $7fFFffFF) 

was ist das $7fFFffFF???
[size=9]Pro|gram|mier|er: Ein Organismus, der Koffein in Software umwandelt.
Geben Sie eine beliebige 11-stellige Primzahl ein, um fortzusetzen...

BladeRunner

Moderator

BeitragSo, Jul 03, 2005 14:07
Antworten mit Zitat
Benutzer-Profile anzeigen
Das ist ne Hexadezimal Zahl. Abwechselnd gross und klein nur damit ich bei den Stellen nicht durcheinander komme. $7fFFffFF entspricht genau den gesetzten 31 ersten bit eines Integers und ist somit die Maske um das Vorzeichenbit zu unterdrücken. Wink
Zu Diensten, Bürger.
Intel T2300, 2.5GB DDR 533, Mobility Radeon X1600 Win XP Home SP3
Intel T8400, 4GB DDR3, Nvidia GF9700M GTS Win 7/64
B3D BMax MaxGUI

Stolzer Gewinner des BAC#48, #52 & #92

Lunatix

BeitragSo, Jul 03, 2005 14:14
Antworten mit Zitat
Benutzer-Profile anzeigen
Äh...Aha. Was bringt das nun genau? in normal-Deutsche sprache mein ich
[size=9]Pro|gram|mier|er: Ein Organismus, der Koffein in Software umwandelt.
Geben Sie eine beliebige 11-stellige Primzahl ein, um fortzusetzen...

BladeRunner

Moderator

BeitragSo, Jul 03, 2005 14:21
Antworten mit Zitat
Benutzer-Profile anzeigen
Der Timer funktioniert auch wenn der Rechner länger als 20 Tage an ist Wink

Millisecs zählt immer weiter hoch, je länger der Rechner läuft. Irgendwann ist der Rechner so lange an, dass die Zahl das Vorzeichenbit erreicht (dieses bit sagt BB ob die Zahl in der Variable positiv oder negativ ist). Ab dann gibt Millisecs() negative Zahlen zurück, und der Timer würde nicht mehr funktionieren.

Wenn es Dich verwirrt kannst Du die Maskiererei auch weglassen, es ist wirklich nur nötig wenn der Rechner des Benutzers sehr lange ohne Unterbrechung läuft.
Ich wollte nur auch diesen Fall mit abdecken, da ich diesen Fehler schon mal hatte, und bis ich herausfand woran es lag hatte ich einige graue Haare mehr Wink
Zu Diensten, Bürger.
Intel T2300, 2.5GB DDR 533, Mobility Radeon X1600 Win XP Home SP3
Intel T8400, 4GB DDR3, Nvidia GF9700M GTS Win 7/64
B3D BMax MaxGUI

Stolzer Gewinner des BAC#48, #52 & #92
 

BIG BUG

BeitragSo, Jul 03, 2005 19:34
Antworten mit Zitat
Benutzer-Profile anzeigen
Wenn ich jetzt nicht grad einen Denkfehler drin habe, liegt das Langzeitproblem nicht an den negativen Werten, sondern vielmehr daran, dass die Zeit wieder von unten anfängt. Dein AND-Befehl bringt also auch nix, vielmehr müsste die Startzeit neu gesetzt werden, wenn es zum Umschalten(bzw Vorzeichenwechsel) kommt...
B3D-Exporter für Cinema4D!(V1.4)
MD2-Exporter für Cinema4D!(final)
 

Dreamora

BeitragSo, Jul 03, 2005 19:43
Antworten mit Zitat
Benutzer-Profile anzeigen
Es geht auch einfacher:

tDiff = abs (millisecs () - old_time)

Das funktioniert von 2 Ausnahmen abgesehen immer.
Diese zwei Ausnahmen sind wenn die zwei Werte verschiedene Vorzeichen haben, was 1x alle 24 Tage uptime passiert. Nämlich wenn Millisecs () > Max Int und wenn Millisecs () von -1 auf 0 wechselt.
Ihr findet die aktuellen Projekte unter Gayasoft und könnt mich unter @gayasoft auf Twitter erreichen.

BladeRunner

Moderator

BeitragSo, Jul 03, 2005 20:11
Antworten mit Zitat
Benutzer-Profile anzeigen
Geht schon mit dem AND, Bigbug. Ist schon mehrfach im harten Einsatz gewesen Wink
Dreams Lösung ist natürlich auch nett.
Zu Diensten, Bürger.
Intel T2300, 2.5GB DDR 533, Mobility Radeon X1600 Win XP Home SP3
Intel T8400, 4GB DDR3, Nvidia GF9700M GTS Win 7/64
B3D BMax MaxGUI

Stolzer Gewinner des BAC#48, #52 & #92

Neue Antwort erstellen


Übersicht BlitzBasic FAQ und Tutorials

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group