Framerate begrenzen mit GetTickCount und Sleep nicht gut?



  • Hi,

    ich wollte meine Framerate begrenzen, das hab ich einfach so versucht:

    while(GetTickCount() <= LastFrameTime + 1)
        Sleep(1);
    
    LastFrameTime = GetTickCount();
    

    Allerdings begrenzt das meine ca. 85 Frames die Sekund schon auf 60, das sollte mit 1 ms verzögerung doch noch nicht sein, oder?
    Es soll nur die schnellen Rechner gebremst werden, nicht die langsamen, bei meinem Freund ist es ohne begrenzung ca 35, mit ca 22...
    Gibst da ne bessere Methode?

    [ Dieser Beitrag wurde am 30.06.2003 um 18:50 Uhr von TheToast editiert. ]



  • Original erstellt von TheToast:
    ich wollte meine Framerate begrenzen

    wozu?


  • Mod

    normalerweise läuft der logictick mit einer konstanten rate und die framerate hängt von dem pc ab.

    da die logic konstant läuft, ist es egal wieviel fps du hast, wäre ja blöd wenn wegen zu schneller rechner ein programm zu schnell abläuft (so wie's früher war) oder wenn ich nur 15fps auf ner super kiste haben, bloss damit jemand mit ner tnt 16mb noch mithalten darf.

    also seperier immer logic von grafik und du wirst nie ein problem haben.

    übrigens kann der sleepbefehl dazu führen dass andere nebenbei laufende programme ab und zu stocken, ich weiß nicht weshalb, aber leider passiert das manchmal.

    rapso->greets();



  • Nein, mit jedem Frame wird jedes Object so und soviel Pixel weiterbewegt. Ich finde das einfacher, einfach die Objekte zu bewegen, und dann den Frame nue zu zeichnen. Das Spiel geht eh nicht übers Netzwerk, deswegen ist das egal. Ich hab z.B. 85 Frames die Sekunde, langsamer stört nicht unbedingt, aber wenn jemand (auch ein Freund) 220 FPS hat, dann gehts definitiv zu schnell.



  • also seperier immer logic von grafik und du wirst nie ein problem haben.

    Beim nächsten SPiel, wird mir jetzt zuviel Arbeit das ganze unzustellen. Ist eh nur ein recht simples spiel... 🙂


  • Mod

    berechnest du grafik und logic gleichzetig?

    rapso->greetS();



  • Sieht ungefähr so aus:

    while(GameActive)
    {
    Gegner Bewegen, Projektile bewegen, Kollisionstest

    Backbuffer zeichnen

    Flip

    // hier soll dann etwas hin, das, wenn die Zeit für einen Schleifenduchgang noch nicht voll ist, etwas wartet.

    }



  • mit Sleep(0) verzichtest du ja auf die deinem Thread noch zustehende Laufzeit und sagst Windows, dass es einen anderen Thread aktivieren soll. Dann musst du eben warten, bis Windows deinen Thread wieder aktiviert.
    Dazu gibt's übrigens auch nen Thread in den FAQ 😉



  • hmm, ja natürlich, mit 1 hatte ich es vorher ausprobiert, das macht das trotzdem Langsamer eine Framebegrenzeng, die pro Frame 1 ms zulässt, sollte 80 Frames die Sekunde nicht auf 60 runterbremsen. Die Framebegrenzung soll auf einen Maximalwert bremse, drunter ist nicht schlim aber mit 220 ist es zu schnell.



  • Lass doch das Sleep einfach ganz weg:

    while(GetTickCount() < LastFrameTime + 20) { }
    

    So soltest du max. eine Framerate von 50 Frames pro Sekunde bekommen
    Framebremse



  • Original erstellt von rapso:
    normalerweise läuft der logictick mit einer konstanten rate und die framerate hängt von dem pc ab.

    seltsam was du da schreibst! wie soll man das schaffen???
    die logic muss ja auch irgendwas TUN (rechnen, kollisionen erkennen,...) und kann doch nicht auf jedem PC gleich schnell sein!! wie willst du denn das machen?
    da müsstest du ja auch auf den kleinsten gemeinsamen nenner gehen was SCHLECHT ist



  • Original erstellt von <gta3vicecity>:
    [quote]Original erstellt von rapso:
    [qb]normalerweise läuft der logictick mit einer konstanten rate und die framerate hängt von dem pc ab.

    seltsam was du da schreibst! wie soll man das schaffen???
    die logic muss ja auch irgendwas TUN (rechnen, kollisionen erkennen,...) und kann doch nicht auf jedem PC gleich schnell sein!! wie willst du denn das machen?
    da müsstest du ja auch auf den kleinsten gemeinsamen nenner gehen was SCHLECHT ist[/QB][/QUOTE]

    jo, finds auch irgendwie komisch 🙂
    also ich würde (und mache) es einfach so dass es eine Variable namens frametime gibt, diese in jedem frame aktualisiert wird, und dann mit allen bewegungen multipliziert wird



  • Original erstellt von DasPinsch:
    jo, finds auch irgendwie komisch 🙂
    also ich würde (und mache) es einfach so dass es eine Variable namens frametime gibt, diese in jedem frame aktualisiert wird, und dann mit allen bewegungen multipliziert wird

    ...und genau das wird er wohl mit "Logic-Tick" meinen...

    ->> High Performance Counter !



  • @topic: Ja.



  • Flenders: Das ist ja das seltsame, wenn ich das so wie du mche, hab ich anstatt 85 Frames nur 33. Wen ich als Versögerung nur 1 (!) ms nehme, sollte sich nichts verzögern, weil ich nur 85 Frames die Sekunde habe, d.h. jeder Frame braucht bereits etwas über 11 ms, trotzdem wirds dann nur 65 anstatt 85. Das kann doch nicht sein...
    Selbst so:

    while(GetTickCount() <= LastFrameTime) {}

    bleiben es noch immer 65...

    [edit]
    Hier ist auch schon der Grund, aus der MSDN zu GetTickCount:

    Windows NT 3.5 and later The system timer runs at approximately 10ms.
    Windows NT 3.1 The system timer runs at approximately 16ms.
    Windows 95 and later The system timer runs at approximately 55ms.

    WIe geht dennd as mti den High Performance Countern?
    [/edit]

    [ Dieser Beitrag wurde am 30.06.2003 um 22:53 Uhr von TheToast editiert. ]



  • Original erstellt von TheToast:
    WIe geht dennd as mti den High Performance Countern?

    Laut Mr. Google so ...


  • Mod

    Original erstellt von DasPinsch:
    jo, finds auch irgendwie komisch 🙂
    also ich würde (und mache) es einfach so dass es eine Variable namens frametime gibt, diese in jedem frame aktualisiert wird, und dann mit allen bewegungen multipliziert wird

    so wie du das machst kann es unvorhergesehene ergäbnisse geben. z.B. wenn die framerate bei 1fps liegt, dann würden vielleicht ein paar objekte in ihrer collisionsberechnung durcheinander durch fliegen oder aneinander vorbei (falls es eine rotation ist). wenn du eine konstante zeit hast, kannst du abschätzen ob das möglich ist und versuchen alles so einzustellen, dass das nicht passiert.

    naja, hier ein source von mir.

    int LastTick=GetTickCount();
        while(!g_bQuit)
        {
            while(LastTick<GetTickCount())
            {
                g_pAktualModule->LogicTick();
                LastTick+=TICKTIME;
                if(LastTick+10000<GetTickCount())
                    LastTick=GetTickCount()+TICKTIME;
            }
            Render();
            if(PeekMessage(&msg,hWnd,0,0,PM_NOREMOVE)!=0)
            {
                g_bQuit = !((bool)(PeekMessage(&msg,hWnd,0,0,PM_REMOVE)));
                TranslateMessage(&msg);
                DispatchMessage(&msg);
            }
        }
    

    für die logic vergehen so immer 40ms, wenn die framerate kleiner als 25 ist, wird die logic öfter aufgerufen und bei einer höcheren framerate seltener als die.

    damit das im spiel alles flüssig ausschaut muss man natürlich animatoren haben, die abhängig von der rendering time sachen anzeigen aber im logictick ihr setup bekommen.

    rapso->greets();



  • mach es einfach so wie David Scherfgen es in seinem Buch beschreibt. :o 🕶



  • Original erstellt von rapso:
    damit das im spiel alles flüssig ausschaut muss man natürlich animatoren haben, die abhängig von der rendering time sachen anzeigen aber im logictick ihr setup bekommen.

    Wie meinen??
    Ich versteh nicht wozu das gut sein soll öfter zu rendern als die Frequenz der logicticks. Denn zwischen zwei logicticks hat sich ja nichts verändert?


  • Mod

    dazu sind die animatoren, diese animieren ohne logic die objekte

    z.B. kann ein keyframe animator die bewegung eines bots animieren, wenn ihn die logic dazu eingestellt hat, deswegen hab ich ja extra die animatoren erwähnt.

    partikelsystem wäre auch ein beispiel dafür.

    viele spiele haben einen viel niedrigereren logictick als ihre framerate, weil das performance bringt, einfacher zu programmieren ist (immer gleiche timediff) und das spiel gleich abläuft, egal welche performance der rechner zu bieten hat.

    rapso->greets();


Anmelden zum Antworten