Timer zu langsam
-
Danke für den Tipp.
O.k., aber meine eigentliche Frage ist noch offen. Hat irgendwer eine Idee?
-
NES-Spieler schrieb:
Gibt es eine Funktion, die immer läuft, egal, was passiert?
Nicht auf einem Betriebssystem, das kein Echtzeitbetriebssystem ist, wie z.B. Windows. Du musst damit rechnen, dass dein Programm im Prinzip beliebig lange Pausen einlegt, wenn gerade Wichtigeres zu tun ist.
Wofür glaubst du denn, das zu brauchen?
-
NES-Spieler schrieb:
Danke für den Tipp.
O.k., aber meine eigentliche Frage ist noch offen. Hat irgendwer eine Idee?
Na wenn du die vergangene Zeit mit einem Vorgegebenen Wert vergleichst ist es ein Timer!
Was ist denn jetzt noch offen??
-
Vielleicht hilft dir ja das hier weiter: http://www.c-plusplus.net/forum/viewtopic-var-t-is-118510.html
-
Nicht auf einem Betriebssystem, das kein Echtzeitbetriebssystem ist, wie z.B. Windows. Du musst damit rechnen, dass dein Programm im Prinzip beliebig lange Pausen einlegt, wenn gerade Wichtigeres zu tun ist.
Ich meine ja nicht, daß die Funktion wirklich immer ausgeführt wird. Worum es mir ging, war folgendes: Die Funktion OnTimer wird nach dem Aufruf der Funktion SetTimer gestartet und wiederholt sich in regelmäßigen Abständen (dem Intervall), bis sie beendet wird. DefWndProc wird jedesmal aufgerufen, wenn eine Windowsnachricht gesendet wird. OnKeyDown wird ausgeführt, wenn eine Taste gedrückt wurde. Und so weiter. Ich wollte nun wissen: Gibt es eine Funktion, die losgeht, wenn das Programm gestartet wird, und die dann nach jedem Durchlauf wiederholt wird, bis das Programm beendet ist? Also eine Funktion, die quasi "immer" aktiv und am Laufen ist.
Wofür glaubst du denn, das zu brauchen?
Für Videospiele. Sobald der Spieler auf eine Taste drückt, wird der Timer gestartet, der die Bewegung der Figur ausführt. Beim Loslassen der Taste wird der Timer gestoppt. Jetzt stell Dir mal vor, der Bildschirm ist 400 Pixel breit und das Männchen soll sich pro Schritt jeweils nur einen Pixel bewegen. Der würde ewig brauchen. Ich müßte dann die Schrittweite erhöhen, was ich aber nicht will, da dann logischerweise eine pixelgenaue Bewegung nicht mehr möglich ist.
Na wenn du die vergangene Zeit mit einem Vorgegebenen Wert vergleichst ist es ein Timer!
Was ist denn jetzt noch offen??Ich kann die Zeiten zwar miteinander vergleichen, aber ich brauche noch eine Stelle im Programm, die das auch tatsächlich zu jedem Zeitpunkt tut, eben eine Funktion, die ständig durchläuft.
Vielleicht hilft dir ja das hier weiter: http://www.c-plusplus.net/forum/viewtopic-var-t-is-118510.html
Tut mir leid, das hilft mir nicht. Der einzige Beitrag, der die dortige Frage beantwortet, ist der mit dem Link zu Visual C++ 6 in 21 Tagen. (Und dieses Tutorial kenne ich schon. Da geht es nur um die normale OnTimer-Funktion, die mir ja eben zu langsam ist.) Danach streiten die sich nur noch über Sleep.
P.S.: Eine Angabe in meinem ersten Text war falsch: Der Timer braucht mit dem Hochzählen von 0 auf 220 nicht drei, sondern 12(!) Sekunden.
-
NES-Spieler schrieb:
Wofür glaubst du denn, das zu brauchen?
Für Videospiele. Sobald der Spieler auf eine Taste drückt, wird der Timer gestartet, der die Bewegung der Figur ausführt. Beim Loslassen der Taste wird der Timer gestoppt. Jetzt stell Dir mal vor, der Bildschirm ist 400 Pixel breit und das Männchen soll sich pro Schritt jeweils nur einen Pixel bewegen. Der würde ewig brauchen. Ich müßte dann die Schrittweite erhöhen, was ich aber nicht will, da dann logischerweise eine pixelgenaue Bewegung nicht mehr möglich ist.
Dieses Problem kannst du nicht lösen. Was immer du tust, es gibt immer Rechner, die so wenig Rechenleistung haben (oder auf denen soviel anderes Zeug läuft), dass dein Programm das Intervall nicht einhalten kann.
Der übliche Weg ist auch nicht der, dass das Spiel versucht, ein möglichst genaues Intervall zu erreichen, um dann eine festgelegt Bewegung auszuführen. Ein Spiel rechnet so schnell wie es kann, und die Bewegungsweite wird aus der verstrichenen Zeit berechnet. So löst man auch gleich das Problem mit unterschiedlich schnellen Rechnern.
-
WAS
12! Sekunden also 479001600 Sekunden?
Tschuldigung schlechter Scherz am Rande. Es kommt mir aber auch recht lang vor bis 220 in 12 Sekunden (da ist ja mein Polo schneller
) [tschuldigung hab glaub Clown gefrühstückt]
zeig doch mal die Funktion vielleicht hängts ja woanders
-
NES-Spieler schrieb:
Vielleicht hilft dir ja das hier weiter: http://www.c-plusplus.net/forum/viewtopic-var-t-is-118510.html
Tut mir leid, das hilft mir nicht. Der einzige Beitrag, der die dortige Frage beantwortet, ist der mit dem Link zu Visual C++ 6 in 21 Tagen. (Und dieses Tutorial kenne ich schon. Da geht es nur um die normale OnTimer-Funktion, die mir ja eben zu langsam ist.) Danach streiten die sich nur noch über Sleep.
Und den Streit solltest du lesen. C++ Freak versuchte uns zu erklären, wie man "richtige" Timer selber machen kann.
-
Polofreak schrieb:
zeig doch mal die Funktion vielleicht hängts ja woanders
Ich kann mir das durchaus vorstellen. WM_TIMER ist für solche Anwendungsfälle nicht geeignet (und auch nicht gedacht).
-
OK tut mir leid, wenn MFK das sagt kannste davon ausgehen, dass da ziemlich nicht mehr viel zu machen ist (ich zieh meinen Hut vor MFK) Somit muss ich mich wohl an dieser Stelle zurück ziehen.
-
zeig doch mal die Funktion vielleicht hängts ja woanders
Welche Funktion? Also ein konkretes Spiel hab ich momentan nicht vorliegen. Das ist mir nur mal beim Testen aufgefallen. Aber folgendes sollte auch reichen:
//... void CMeinProgrammDlg::OnInitDialog () { //... m_nZahl=0; m_nTimer=0; //... } void OnKeyDown (UINT nChar, UINT nRepCnt, UINT nFlags ) { if (m_nTimer==0) //Verhindert, daß der Timer mehrmals aufgerufen wird. { MessageBox ("Start"); m_nTimer=SetTimer (1, 1, NULL); } //... } void OnTimer (UINT nIDEvent) { m_nZahl++; if (m_nZahl==220) { KillTimer (nIDEvent); m_nTimer=0; MessageBox ("Stop"); } //... } //...
Das sollte reichen, um es zu demonstrieren. Wenn Du nun die Zeit zwichen den beiden Message Boxen mißt, kommst Du auf circa 12 Sekunden. Und das ist zu lang. 220*1ms=220ms und nicht 12s.
-
Und den Streit solltest du lesen. C++ Freak versuchte uns zu erklären, wie man "richtige" Timer selber machen kann.
Ja, aber seine Methode mit der Sleep-Funktion ist wirklich nicht die Lösung. Die hält nämlich das gesamte Programm an und ist kein Timer in dem Sinn.
-
Imho ist der Grund ganz einfach:
So ein Timer ist ja eine Nachricht.
Und wenn so ein Timer rausgeht, dann dauert das einen Moment, bis er ankommt. (Verzögerung 1)
Dann hat dein Windows ja noch mehr zu tun als Timer verarbeiten, die müssen sich also hinten anstellen. (Verzögerung 2)
Das was du in der Funktion machst, kostet auch nochmal Zeit.Ich meine irgendwo gelesen zu haben, dass man Werte unter 50 gar nicht erst nehmen braucht, weil Timer so ungenau sind.
Du wirst dir wohl etwas anderes suchen müssen.
-
Nur mal so am Rande. Du kannst da zwar 1 ms angeben, aber irgendwo steht auch (oder ich habe es woanders gelesen), dass der kleinste zuverlässige Werte zwischen 10 und 100 ms liegt. Ich weiss, große Zeitspanne, bin mir aber bei dem genauen Wert nicht so sicher.Dann sind es im schlimmsten Fall 220*100 ms = 22000 ms = 22 Sek. Also ist es wahrscheinlicher das du so bei ca. 50ms liegst.
-
estartu_de schrieb:
Und wenn so ein Timer rausgeht, dann dauert das einen Moment, bis er ankommt. (Verzögerung 1)
Dann hat dein Windows ja noch mehr zu tun als Timer verarbeiten, die müssen sich also hinten anstellen. (Verzögerung 2)Timer-Nachrichten werden überhaupt erst dann abgearbeitet, wenn keine Nachrichten mit hoher Priorität in der Message Queue steht (Verzögerung 3)
Es kann auch immer nur eine Timer-Nachricht in der Queue stehen -> Timer-Ereignisse gehen verloren.
-
NES-Spieler schrieb:
Und den Streit solltest du lesen. C++ Freak versuchte uns zu erklären, wie man "richtige" Timer selber machen kann.
Ja, aber seine Methode mit der Sleep-Funktion ist wirklich nicht die Lösung. Die hält nämlich das gesamte Programm an und ist kein Timer in dem Sinn.
Tja, ab DER Stelle haben wir es ja auch nicht mehr verstanden. Er beharrte darauf, dass es trotzdem ginge und dann schief die Diskussion ein.
-
Zusatz zu Estartu:
Und er bildete Nonsens-Phrasen um zu beeindrucken, so dass niemand mehr versteht was er da eigentlich behauptet
und niemand mehr was dazu sagt (zumindest das hat fast geklappt)
-
O.k., fragen wir doch mal so: Wie macht man das normalerweise, wenn man einen Timer braucht, der recht zügig sein soll? Wenn Ihr ein Männchen von links nach rechts bewegen wolltet, wie würdet Ihr das mit der Zeit zwischen zwei Schritten realisieren? Sleep, wie gesagt, funktioniert nicht und hält das ganze Programm an. Und die Version
void OnKeyDown (UINT nChar, UINT nRepCnt, UINT nFlags) { switch (nChar) { case VK_RIGHT: m_Spielfigur.GoRight (); //oder was auch immer break; case VK_LEFT: m_Spielfigur.GoLeft (); break; } CDialog:OnKeyDown (nChar, nRepCnt, nFlags); }
ist ja auch nicht das Wahre, denn erstens sieht so eine Bewegung abgehackt aus und zweitens dürfte hier die Geschwindigkeit sowohl von der Geschwindigkeit des PCs generell als auch von der eingestellten Wiederholrate der Tastatur abhängen. (Nicht zu reden von computergesteuerten Gegnern, auf die diese Möglichkeit gar nicht anwendbar ist.)
Also, was macht man in dem Fall? Irgendwie muß das doch gehen.
P.S.: Bitte erklärt mir jetzt nicht, daß man mit der MFC keine Spiele programmiert! Das ganze Problem (der lahme Timer) könnte man nämlich auch auf reine WinAPI-Programme beziehen. Da ist es genauso.
-
NES-Spieler schrieb:
Wenn Ihr ein Männchen von links nach rechts bewegen wolltet, wie würdet Ihr das mit der Zeit zwischen zwei Schritten realisieren?
Pass die Schrittweite der Zeit an, nicht umgekehrt.
Wie ich vorher schon mal geschrieben habe: Mach das, was zwischen zwei Frames zu tun ist, miss nach, wie lange das gedauert hat, und bewege dann das Männchen um eine Strecke, die dieser Zeit entspricht. Pausen bringen dich nicht überhaupt nicht weiter. Mit Pausen bekommst du nur dann eine halbwegs konstante Geschwindigkeit hin, wenn du auf einen Großteil der Prozessorleistung verzichtest. Wenn du auf unterschiedlich schnellen Systemen trotzdem ähnliche Geschwindigkeiten erzielen willst, geht es mit Pausen gar nicht.
Bitte erklärt mir jetzt nicht, daß man mit der MFC keine Spiele programmiert!
Jedenfalls benutzt man die Windows-Messagequeues nicht für die Steuerung von zeitlichen Abläufen oder Ein-/Ausgabe. Weder mit MFC noch ohne.
-
Du könntest dir mal ein Buch holen in dem steht wie man es richtig macht!