Framerate begrenzen mit GetTickCount und Sleep nicht gut?


  • 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();



  • man trennt es einfach deshalb, weils schlicht sinnvoller ist.

    eine logikaktualisierung von 85 mal in der sekunde macht keinen sinn, denn kein mensch kann so schnell das spiel steuern, oder ist in der lage so viele änderungen pro sekunde wahrzunehmen. selbst 60 oder 40 mal ist schon fast zu viel. 25 reicht aus. ABER es ist nicht egal, ob man nur 40 oder 60 GraphicFramesPS hat, denn auf einem monitor mit 100 hertz sehen 60 oder 80 fps einfach scheisse aus. man sollte immer mehr fps als die bildwiederholfrequenz haben, damit die grafik auch gut aussieht. grafik und logik sind zwei verschiedene dinge und sollten deshalb auch getrennt gehandhabt werden. ausserdem kann die logik unter umständen bei 100 hertz ZU rechenintensiv sein (z.b. wenn man 10000 einzelobjekte hat und sich alle in jedem frame ändern). da macht es einfach keinen sinn sie so oft neu zu berechnen (weil man einen 3 gigahertz rechner bräuchte)

    einen normalen mainloop würde ich so realisieren.

    do {
      if (Timer.GetMilliSeconds()>=(1000/25))
      {
        Timer.StartNewTimeFrame();
        UpdateLogic(); //wird nur alle 25 mal in der sekunde ausgeführt
      }
    
      RenderScene(); //fullspeed, also ohne bremse
      SwitchBuffers();
    } while(!Quit);
    

    wenn dann der rechner alles schneller als 25 mal in der sekunde berechnen kann, dann wird das halt gemacht und die logik wird ganz normal gebremst. wenn der rechner zu langsam ist, dann wird alles auf einmal langsamer. ich halte nichts von einer multiplikation mit der vergangegen zeit auf die bewegungen. das führt nur zu ruckeligen und sprunghaften bewegungen, und macht das spiel unter umständen unspielbar (falls das programm ein spiel ist). aber auch wenn der rechner das programm schnell genug berechnen kann, führt das zu rucklern (wenn auch nur marginal), da jeder einzelne frame nicht immer 100,000000000% gleichschnell berechnet wird. zum einen weil sich einfach zuviel pro frame ändert und dadurch die rechenzeit schwankt, aber auch deshalb, weil es noch andere prozesse gibt, die auch unterschiedliche rechenzeiten haben.

    letzen endes ist es aber geschmacksache! in vielen spielen wird die erste variante genommen, denn wenn man dort einen zu lahmen rechner hat, bewegt sich alles in zeitlupe und nicht in sprüngen. (hat schon mal jemand starcraft mit 4000 zerglingen auf nem 600mhz rechner gezockt? 😃 )



  • Original erstellt von KXII:
    [QB]
    eine logikaktualisierung von 85 mal in der sekunde macht keinen sinn, denn kein mensch kann so schnell das spiel steuern, oder ist in der lage so viele änderungen pro sekunde wahrzunehmen. selbst 60 oder 40 mal ist schon fast zu viel. 25 reicht aus. ABER es ist nicht egal, ob man nur 40 oder 60 GraphicFramesPS hat, denn auf einem monitor mit 100 hertz sehen 60 oder 80 fps einfach scheisse aus. man sollte immer mehr fps als die bildwiederholfrequenz haben, damit die grafik auch gut aussieht.

    mainloop würde ich so realisieren.

    [QB]

    Naja, das mit mehr Frames als die Hertzzahl glaub ich eher nicht dran. Ein normaler fernseheher hat 50 oder 100 Hertz, aber es werden nur 25 Bilder pro Sekunde gezeigt. Auerdem wird ein Frame ja in den Bildschirmspeicher gezeichnet, und idesen sendet die Grafikkarte halt je nach Wiederholfrequenz an den Monitor. Außerdem ist bei mir die FPS von der Wiederholfrequenz des Monitors abhängig. Ich schaff bei mir keine schnellere FPS als WIederholrate. Bei 85 Hertz kommen bei mir 85 FPS, bei 65 Hertz nur 62 FPS.
    Ich versteh trotzdem nicht, wieseo man mehr Logicticks als FPS braucht, wenn was in der logik verändert wird, muss es doch auf den Bildschirm gezeichnet werden. Ich meine, wieso soll man ein Objekt zweilmal veschieben, wenn es nru einmal gezeichnet wird? Dan kann man da sObjekt doch einfach einmal um das doppelte verschieben und dann zeichnen, oder?


  • Mod

    damit die logic nicht durcheinander kommt, z.B. bei der collisionsberechnung, bei der positionierung der objekte... wenn ein objekt immer 4 einheiten in x verschoben wird pro tick,könnte es bei 24fps anstatt 25logicticks zu winzigen ungenauigkeiten kommen, die auch noch unnütz wären, anstatt die bewegung * timedelta zu rechnen, kann man vom gleichen delta ausgehen und sparrt einiges an berechnungen

    und in extrem fällen:

    angenommen da ist ne wand mit einer tür, die dann in einer sekunde aufgeschlagen wird und du berechnest mit jedem echtem frame die logic, da die tür aufgeht, öffnest du ein protal und es müssen einige dinge geladen werden und die fps fällt kurz auf 1fps, nämlch die zeit die die tür aufgeht.
    du berechnest dafür dann kolisionen für deinen avater der vor der tür stand, normalerweise hätte die tür nicht durch ihn durchgehen können, aber weil du einmal

    ----0-----0-----
    X
    und dann
    ----0-----0-----
    /
    / X
    /
    /

    hast, bemerkst du selbst wenn du zwischen den vertices rays ziehst, vielleicht keine kollision.

    das ist an sich nicht superschlimm, aber es ist eben unvorhersehbar, denn bei der nächsten tür schon könnte alles im cache sein und der typ läuft da erst ein paar mal gegen und wundert sich, weshalb die "schei**" tür nicht aufgeht.
    das känn bei größeren sachen ganz schön ärgerlich sein, z.B. eine zuschnappende falle die nen gegner töten sollte und wegen nachladen oder sonstiger lustigkeiten ihn übersprang.

    ich hab schonma spiele gespielt, bei denen die HD plötzlich wieder anging und als die an war, befand ich mich irgendwo außerhalb der level, bin runtergefallen und war tod..., sicher kann man das abfangen, aber nicht vorhersehen.

    rapso->greets();



  • @thetoast

    ich kann dir leider keine physikalische erklärung dafür geben, warum das so ist, aber bei mir ist das so mit den mehr fps als hertz. für mich sieht animierte grafik einfach besser aus, wenn sie mehr fps hat als die bildwiederholrate des monitor. das bezieht sich natürlich nur auf so kleinigkeiten wie ruckler oder sauberes scrolling. die grafik selber wird nicht besser (ist aber klar...). vielleicht fällt dir das einfach nur nicht auf, oder du siehst keinen unterschied, weil du noch nie so genau hingeschaut hast. keine ahnung wieso das bei mir so ist, es ist aber so, und du kannst mir das auch ruhig glauben.

    wieso schafft dein rechner nicht mehr fps als hertz? wenn du keine spezialhardware hast, dann sollte das bei dir auch gehen. was passiert denn, wenn du ein directx sdk demo startest, das normalerweise so 300-400 fps hat?

    zum thema mehr logikticks als fps. du hast recht. es macht im normalfall keinen sinn öfters die logik zu berechnen, als sie dargestellt wird. in extrem fällen vielleicht schon, aber die sind meistens sehr exostisch. zum beispiel, wenn man in echtzeit eine hardware abtastet. wenn dann die grafikarte die daten nur mit 1 frame pro sekunde darstellen kann, es aber noch andere "einheiten" gibt, die die daten öfters benötigen, als nur einmal pro sekunde, dann sollte man einen extra thread nur für die logik benutzen und diesen dann die logik öfters als einmal pro sekunde berechnen lassen. sonst würde man ja den gesamten programmablauf durch die grafikdarstellung begrenzen.

    @rapso

    "damit die logic nicht durcheinander kommt, z.B. bei der collisionsberechnung, bei der positionierung der objekte... wenn ein objekt immer 4 einheiten in x verschoben wird pro tick,könnte es bei 24fps anstatt 25logicticks zu winzigen ungenauigkeiten kommen, die auch noch unnütz wären, anstatt die bewegung * timedelta zu rechnen, kann man vom gleichen delta ausgehen und sparrt einiges an berechnungen

    warum sollte, egal wo, logik durcheinander kommen? warum sollte es bei 24 fps anstatt 25 logikticks zu ungenauihkeiten kommen? für mich hört sich das schwachsinnig an (sorry). denn wenn ein rechner nicht mehr als 25 fps berechnen kann, dann wird halt alles einfach langsamer berechnet und das spiel fangt an in zeitlupe abzulaufen. aber die logik arbeitet nach wie vor genauso und wenn man es richtig programmiert, dann ergeben sich auch keine probleme bei der kollision oder so und es kommt auch nichts durcheinander!

    ..., bemerkst du selbst wenn du zwischen den vertices rays ziehst, vielleicht keine kollision.

    warum sollte man keine kollision erkennen? wie ich schon oben sagte, spielt das keine rolle. wenn doch dann ist es einfach schlecht programmiert, weil es nicht alle fälle abdeckt, die eintreten können.

    deshalb auch folgendes:

    ich hab schonma spiele gespielt, bei denen die HD plötzlich wieder anging und als die an war, befand ich mich irgendwo außerhalb der level, bin runtergefallen und war tod..., sicher kann man das abfangen, aber nicht vorhersehen.

    wofür sollte man es auch vorhersehen oder abfangen? wenn eine hd in aktion tritt und daten von ihr geladen werden, dann wird das spiel halt etwas langsamer oder es bleibt sogar ganz stehen (je nach programmierung), bis die zugriffe fertig sind, das ändert aber nichts an der berechenbarkeit von kollisionen. sorry, ich sehe hier keine probleme.

    [ Dieser Beitrag wurde am 02.07.2003 um 01:18 Uhr von KXII editiert. ]



  • Original erstellt von KXII:
    für mich sieht animierte grafik einfach besser aus, wenn sie mehr fps hat als die bildwiederholrate des monitor...vielleicht fällt dir das einfach nur nicht auf, oder du siehst keinen unterschied, weil du noch nie so genau hingeschaut hast. keine ahnung wieso das bei mir so ist, es ist aber so, und du kannst mir das auch ruhig glauben.

    Das erscheint mir einfach nicht logisch, kannst Du das irgendwie untermauern?

    Original erstellt von KXII:
    wieso schafft dein rechner nicht mehr fps als hertz? wenn du keine spezialhardware hast, dann sollte das bei dir auch gehen. was passiert denn, wenn du ein directx sdk demo startest, das normalerweise so 300-400 fps hat?

    Ich sitze hier an einem 650MHz Rechner mit einer alten GeForce256, ich bin mehr als zufrieden wenn ich Spiele mit 25FPS laufen lassen kann, obwohl ich Deiner Logik zufolge erst ab 90FPS zufrieden sein sollte. (Mein Monitor läuft mit 90Hz bei 1280x1024.)

    Original erstellt von KXII:
    zum thema mehr logikticks als fps. du hast recht. es macht im normalfall keinen sinn öfters die logik zu berechnen, als sie dargestellt wird.

    Doch, macht es (zumindest im weitesten Sinne). 😉
    Wenn diverse Egoshooter nicht seltener rendern würden als die Spiellogik überprüft wird dann gäbe es keine ruckelnden Spiele - es würde einfach alles im Zeitlupentakt ablaufen was - wenn man es sich genau überlegt - wohl noch ungünstiger wäre.


Anmelden zum Antworten