Noch kürzer Warten als Sleep(1)
-
MiC++ha schrieb:
joomoo schrieb:
Warum? Ich programmiere ein Spiel mit Winapi und wenn ich keinen Sleep Befehl einbaue läuft ja alles megaschnell!
Das macht man aber nicht mit sleep, denn jeder ausführungsblock kann unterschiedlich lange dauern und mit sleep() können keine Nachrichten verarbeitet werden.
Mach es so:
/* global */ bool ende = false; int WINAPI WinMain (HINSTANCE hThisInstance, HINSTANCE hPrevInstance, LPSTR lpszArgument, int nFunsterStil) { /* Spiel einrichten, bilder laden und so */ DWORD idle; /* die Spielschleife */ while (!ende) { idle = GetTickCount(); /* aktuellen Millisekundenstand hollen */ /* Nachrichten abhandeln */ while(PeekMessage(&messages, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&messages); DispatchMessage(&messages); } /* Spiel Code */ /* und nun die Frame Bremse */ while ((GetTickCount() - idle) < 40) /* 25 Frame Sekunde */ ; } }
So läuft es nun mit 25 Bilder Sekunde, wie beim Film
Das hat ich auch schon gedacht, aber das geht nicht, da GetTickCount() genauso ungenau ist wie sleep! Ein Tick sind nur ungefähr 10 ms...
-
Eigentlich sollte man bei Games die Bewegungen unabhängig von den Frames, sondern abhängig von der Zeit machen.
Frame-Bremse sollte höchstens benutzt werden, wenn sonst bei schnellen Grakas einige Werte zu klein/zu groß werden um damit noch gescheit rechnen zu können...
...aber die Thematik gehört wohl eher ins Spiele/-Grafikprogrammierungs-Forum...
-
Ich brauche einfach nur einen Ersatz für Sleep() der mindestens ms genau ist...
-
Nein das brauchst du nicht. Hör auf uns.
-
MiC++ha hat doch schon eine Lösung mit Hilfe von QueryPerformanceCounter gepostet, oder funktionierte die nicht?!
-
flenders schrieb:
MiC++ha hat doch schon eine Lösung mit Hilfe von QueryPerformanceCounter gepostet, oder funktionierte die nicht?!
Doch das Funktioiert, nur unter 1000MHz kann mann keine hohe genauigkeit garantieren, aber wer hat weniger als 1000MHz außer meine Frau(500 Celeron)? :::Geitz ist geil:::
Ne mal genau gesagt, wir wissen nicht genau den Zusammenhang, den sagt er auch nichts da er sonst ins Spieleforum verschwindet, aber mit dieser "Wer wird Millionär" raterei, kommen wir auch nicht weiter.
Diese Spielschleife die ich anzeigte kann auch leicht mit QueryPerformanceCounter() verfeinert werden, die allgemeine Regel lautet ::Sleep() vermeiden, und das hat seine Gründe, aber wenn man QueryPerformanceCounter() benutzt auf (ab) einen 800MHz Rechner kann mann sich
schon in guter genauigkeit bewegen (je nach Prozess anzahl).
Solange wir keine genauen Infos haben, bringt das alles nichts, und ich denke wenn diese Infos kommen ist es Vermutlich doch was fürs Spieleforum.Genauer als Sleep
Auch dazu wurden gewisse Antworten gegeben, und bei spielen giebts keine Genauigkeit, sondern so ne Art Ablauf Perfomance, wenn dein Spiel bei dir gut und Genau läuft, muß es nicht gleich auch bei mir genauso gut laufen, und schon gar nicht mit "Schlafen".
-
MiC++ha schrieb:
flenders schrieb:
MiC++ha hat doch schon eine Lösung mit Hilfe von QueryPerformanceCounter gepostet, oder funktionierte die nicht?!
Doch das Funktioiert, nur unter 1000MHz kann mann keine hohe genauigkeit garantieren, aber wer hat weniger als 1000MHz außer meine Frau(500 Celeron)? :::Geitz ist geil:::
Ne mal genau gesagt, wir wissen nicht genau den Zusammenhang, den sagt er auch nichts da er sonst ins Spieleforum verschwindet, aber mit dieser "Wer wird Millionär" raterei, kommen wir auch nicht weiter.
Diese Spielschleife die ich anzeigte kann auch leicht mit QueryPerformanceCounter() verfeinert werden, die allgemeine Regel lautet ::Sleep() vermeiden, und das hat seine Gründe, aber wenn man QueryPerformanceCounter() benutzt auf (ab) einen 800MHz Rechner kann mann sich
schon in guter genauigkeit bewegen (je nach Prozess anzahl).
Solange wir keine genauen Infos haben, bringt das alles nichts, und ich denke wenn diese Infos kommen ist es Vermutlich doch was fürs Spieleforum.Genauer als Sleep
Auch dazu wurden gewisse Antworten gegeben, und bei spielen giebts keine Genauigkeit, sondern so ne Art Ablauf Perfomance, wenn dein Spiel bei dir gut und Genau läuft, muß es nicht gleich auch bei mir genauso gut laufen, und schon gar nicht mit "Schlafen".
Keine genauere Lösung als Sleep wurde gepostet. Außer das mit dem QueryPerformanceCounter, aber das klappt bei mir nicht, denn es wartet plötzlich kürzer wenn man eine Taste gedrückt hält. Keine Ahnung warum. Ich hab aber auch mehr als 1 Ghz (1,83ghz). Aber es muss doch eine Möglichkeit geben? Es gibt doch soviele Spiele die so funktionieren...
-
Es gibt doch soviele Spiele die so funktionieren...
welche?
Ich beschäftige mich auch mit Spieleprogrammierung, aber nur zum teil, aber mir ist nicht bekannt das man irgendwo das Spiel einfriert um die Frames runter zu setzten, es wird meines wissens immer mit Timing gearbeitet.
-
MiC++ha schrieb:
Es gibt doch soviele Spiele die so funktionieren...
welche?
Ich beschäftige mich auch mit Spieleprogrammierung, aber nur zum teil, aber mir ist nicht bekannt das man irgendwo das Spiel einfriert um die Frames runter zu setzten, es wird meines wissens immer mit Timing gearbeitet.
Was ist den Timing?
-
joomoo schrieb:
Was ist den Timing?
Zeitgesteuert!
Ich gebe an wie lange es dauert das sich ein Objekt von Punkt A nach Punk B bewegt, egal ob 20FPS oder 150FPS. Und wenn ich eine Framebremse will, dann mache ich das auf der Art wie schon erwähnt, aber ->Bild ausgeben->Prog schlafen lassen->nächstes Bild ist "FATAL_ERROR_STYLE_FOR_GAME_DEVS"
-
MiC++ha schrieb:
joomoo schrieb:
Was ist den Timing?
Zeitgesteuert!
Ich gebe an wie lange es dauert das sich ein Objekt von Punkt A nach Punk B bewegt, egal ob 20FPS oder 150FPS. Und wenn ich eine Framebremse will, dann mache ich das auf der Art wie schon erwähnt, aber ->Bild ausgeben->Prog schlafen lassen->nächstes Bild ist "FATAL_ERROR_STYLE_FOR_GAME_DEVS"
Und wie gebe ich das an? Wie kann ich Zeit messen??
-
Um das zu Vereinfachen gehen wir mal von einem 2D Game aus und als "Zeit" ms aus GetTickCount(), für 3D emphelt sich äher PerformanceCounter.
sagen wir du hast ein Objekt, egal wie es aus sieht dem giebts du eine geschwindigkeit vor, als Beispiel 200px/Sekunde
DWORD alteZeit, neueZeit; alteZeit = GetTickCount(); /* Spielschleife */ while (!Spielende) { /* hier event. Messages bearbeiten */ /* Hintergrund zeichnen etc. */ /* nun Rechnen wir die Geschwindigkeit in ms um */ float msSpeed = Objekt->Speed / 1000; /* Objekt->Speed ist int 200 */ neueZeit = GetTickCount(); int PixelBewegung = msSpeed * (neueZeit - alteZeit); Objekt->PositionX += PixelBewegung; /* für X Richtung, als Beispiel */ /* und nun das Objekt zeichnen */ /* etc. */ alteZeit = neueZeit; }
Wenn du nun 100FPS hast bewegt es sich um 2 Pixel, hast du 50FPS bewegt es sich um 4 Pixel, in jedem Fall bewegt es sich um 200 Pixel pro Sekunde.
Das war jetzt eine vereinfachte Darstellung zum besseren Verständnis.
-
MiC++ha schrieb:
Um das zu Vereinfachen gehen wir mal von einem 2D Game aus und als "Zeit" ms aus GetTickCount(), für 3D emphelt sich äher PerformanceCounter.
sagen wir du hast ein Objekt, egal wie es aus sieht dem giebts du eine geschwindigkeit vor, als Beispiel 200px/Sekunde
DWORD alteZeit, neueZeit; alteZeit = GetTickCount(); /* Spielschleife */ while (!Spielende) { /* hier event. Messages bearbeiten */ /* Hintergrund zeichnen etc. */ /* nun Rechnen wir die Geschwindigkeit in ms um */ float msSpeed = Objekt->Speed / 1000; /* Objekt->Speed ist int 200 */ neueZeit = GetTickCount(); int PixelBewegung = msSpeed * (neueZeit - alteZeit); Objekt->PositionX += PixelBewegung; /* für X Richtung, als Beispiel */ /* und nun das Objekt zeichnen */ /* etc. */ alteZeit = neueZeit; }
Wenn du nun 100FPS hast bewegt es sich um 2 Pixel, hast du 50FPS bewegt es sich um 4 Pixel, in jedem Fall bewegt es sich um 200 Pixel pro Sekunde.
Das war jetzt eine vereinfachte Darstellung zum besseren Verständnis.Genauso will ich das auch machen. Nur das gibt es dieses eine Problem: GetTickCount() ist verdammt ungenau das ein Tick ca. 12 ms sind. Das reicht mir nicht.
-
MSDN schrieb:
The GetTickCount function retrieves the number of milliseconds that have elapsed since Windows was started.
in alteZeit steht z.B. 120000, nach 10ms (einen Schleifen durchlauf) giebt GetTickCount() 120010 zurück für neueZeit, neueZeit - alteZeit macht somit 10ms.
Du kannst dazu auch den QueryPerformanceCounter verwenden, mußt es dir dann nur so umschreiben.
-
MiC++ha schrieb:
MSDN schrieb:
The GetTickCount function retrieves the number of milliseconds that have elapsed since Windows was started.
in alteZeit steht z.B. 120000, nach 10ms (einen Schleifen durchlauf) giebt GetTickCount() 120010 zurück für neueZeit, neueZeit - alteZeit macht somit 10ms.
Du kannst dazu auch den QueryPerformanceCounter verwenden, mußt es dir dann nur so umschreiben.Das ist leider nicht so. Denn nach 10ms ist noch kein Tick vergangen. Das heißt GetTickCount() ist immer noch 120000. Das ist ja mein Problem.
You typically use GetTickCount to compare the current Windows time with the time returned by the GetMessageTime function. GetMessageTime returns the Windows time when the specified message was created. GetTickCount is limited to the resolution of the system timer.
The system timer runs at approximately 10ms.
Windows Me/98/95: The system timer runs at approximately 55ms.
Windows NT 3.1: The system timer runs at approximately 16ms.
-
joomoo schrieb:
Keine genauere Lösung als Sleep wurde gepostet. Außer das mit dem QueryPerformanceCounter, aber das klappt bei mir nicht, denn es wartet plötzlich kürzer wenn man eine Taste gedrückt hält. Keine Ahnung warum.
Dann liegt das aber nicht daran, dass die Performace Counter falsch arbeiten, sondern dass dein Code falsch ist. Da die Performace Counter spezielle Hardware ist, kann es diesbezüglich auch keine Probleme geben. Ich hab mir vor geraumer Zeit mal 'ne Stoppuhr-Klasse geschrieben, und da hab ich auch die Performance Counter benutzt. Damit hatte ich sowhl auf meinem alten Rechner (AMD Thunderbird 900) sowie auf meinem aktuellen Rechner (AMD Athlon XP 2600) bisher keine Probleme. Wenn's dich interessiert, dann such mal hier im Forum nach chronometer, afair hab ich mal 'ne rudimentäre Version der Klasse gepostet.
-
@joomoo
Deine Aussage kann ich nicht bestätigen, wenn ich folgendes teste:switch (message) { case WM_KEYDOWN: DWORD idle,idle2; idle = GetTickCount(); Sleep(3); idle2 = GetTickCount(); char buffer[80]; sprintf(buffer,"start:%d / ende:%d ",idle,idle2); SetWindowText(hwnd,buffer); break; case WM_DESTROY: PostQuitMessage (0); break; default: return DefWindowProc (hwnd, message, wParam, lParam); }
in der WndProc, dann erhalte ich immer 2 unterschidliche Werte, wobei die differenz zwischen 3 und 8ms liegt, was beweist das Sleep ungenau ist, aber nicht das GetTickCount() mind. alle 10ms aktuallisiert wird, selbst mit sleep(1) war die differenz 2ms, nach deiner aussage müßten die werte aber gleich sein, das ist aber nicht so.
Daher reicht es für normale und die meißten Spiele das aus, was ich vorgab, bei mir klappt es ja auch.EDIT:
und auf 2-3ms kommt das auch nicht drauf an da man es nicht bemerkt, eine Sekunde hat 1000ms.
Wenn du wenig in der Spielschleife machst, so das sie, sagen wir mal 2ms nur benötigt, dann solltest du nur mit float werten arbeiten bei der Bewegung und testen ob >0.5 && <1, ne 1 wählen, etc.
-
Multimedia-Timer (z.B. timeGetTime() ) sollten nochmal genauer sein als z.B. GetTickCount()...
...aber normalerweise wird bei Spielen QueryPerformanceCounter() in Verbindung mit QueryPerformanceFrequency() verwendet und was genaueres liefert die WinAPI wohl auch nicht...
-
geeky schrieb:
Multimedia-Timer (z.B. timeGetTime() ) sollten nochmal genauer sein als z.B. GetTickCount()...
...aber normalerweise wird bei Spielen QueryPerformanceCounter() in Verbindung mit QueryPerformanceFrequency() verwendet und was genaueres liefert die WinAPI wohl auch nicht...Ganz genau so ist es, wie gesagt GetTickCount reicht schon für einige "einfache" Spiele, aber sonst sollte man das mit dem PerformanceCounter lösen, und das jetzt so umzusetzten dürfte bei allen Angaben hier jetzt wohl kein Problem mehr bilden.
-
Hmm, 10ms wären immer noch 100 fps (oder bin ich jetzt blöd ?) - Wieso reicht dir das eigentlich nich ?