While-Schleife Anbremsen auf bestimmte Geschwindigkeit



  • Ich habe ein kleines Spiel in eine While-schleife geschrieben. Auf meinen netbook kann ich es auch gut Spielen, aber wenn ich es auf meinen richtigen PC überspiele wird alles so schnell, dass man es nicht mehr steuern kann.
    Außerdem kommen wehrend des Spieles immer mehr aufgaben dazu, dadurch wird meine Kugel immer langsamer.
    Jetzt würde ich gerne von euch wissen, wie kann ich machen, dass die while-schleife z.B. 30 mal in der Sekunde durchläuft. Egal wie stark der PC oder wie viel er zu tun hat.
    Mir ist klar, dass wenn ein PC an der Grenze seiner Leistung ist, nicht schneller machen kann. Ich will aber einen stärkeren PC die Geschwindigkeit runterdrehen.
    Hat einer von euch eine Idee wie man das lösen kann?

    Ich freue mich auf Antworten,

    Stratege993



  • das suchwort dazu heißt framebremse.
    geht im prinzip so:

    zeit letzterFrame=liesUhrzeit();
    for(;;)
    {
       maleZeugs();
       //ab hier framebremse
       zeit letzterFrame+=1sekunde/30;
       while(liesUhrzeit()<letzterFrame)
          Sleep(1);
    }
    


  • Üblicherweise baut man in Spiele aber nicht so eine Framebremse ein. Man ruft den Logikcode aber in fest definierten Zeitabständen auf. Rendern und Animieren kann man ruhig öfter machen, damit auch die Geforce Ultra XXL Besitzer sagen können, dass sie eine Framerate von 400 haben.

    Gruß
    Don06



  • Zeitbasierte Animationen/Bewegungen verwenden und nicht Framebasierte.



  • warum sollte ein spiel 400 Frames liefern können?
    ich würde als Kompromiss die Framebremse abschaltbar machen.
    Prinzipiell finde ich es sch.. wenn ein spiel, dass mit 500Mhz auskommt trotzdem die 3,5 GH meines Rechner ausnutzt und damit den Stromverbrauch und den lärmpegel sinnlos nach oben dreht.



  • leider macht windows es einem nicht gerade leicht, ein vernünftiges timing zu bewerkstelligen, ohne den prozessor dabei voll auszulasten. es ist fast unmöglich, die hauptschleife bspw. bei hablbwegs stabilen 100 Hz laufen zu lassen und einfach nur die "überschüssige" zeit abzugeben. und mit standardmitteln gehts sowieso nicht.



  • For example:

    while(true) // while app running
    {
    	static unsigned long oldLogicTick = timeGetTime() - 50;
    	static unsigned long oldMoveTick = timeGetTime() - 20;
    
    	// Logic- Tick
    	if(timeGetTime () - oldLogicTick >= 40)
    	{
    		// ...
    		oldLogicTick = timeGetTime();
    	}
    
    	// Move- Tick
    	if(timeGetTime () - oldMoveTick >= 10)
    	{
    		// ...
    		oldMoveTick = timeGetTime();
    	}
    
    	// Graphic- Tick
    	// ...
    }
    

    Musst natürlich an dein Spiel anpassen.



  • jup, Sleep(1); ist vieeel zu grub. wenn erstmal ein anderer prozess den prozessor hat, dann darf ich ruhig davon ausgehen, den prozessor erst 10 oder 15 ms später zu sehen. also macht man in der framebremde kein Sleep(1) oder Sleep(0), sondern {}. aktiv rechenzeitverbraten kann ich dann aber besser, indem ich zeitbasiert animiere und berechne.

    vielleicht ist bei der forderung

    die while-schleife z.B. 30 mal in der Sekunde durchläuft. Egal wie stark der PC
    

    doch ne framebremse mit Sleep noch ok.

    PS: meine augen schaffen eh nicht mehr als 30Hz.



  • Don06 schrieb:

    Man ruft den Logikcode aber in fest definierten Zeitabständen auf. Rendern und Animieren kann man ruhig öfter machen, damit auch die Geforce Ultra XXL Besitzer sagen können, dass sie eine Framerate von 400 haben.

    Die Grafik wird sich aber nicht von sich aus verändern, meistens folgt sie auf Anpassungen der Logik. Dann finde ich es nicht sehr sinnvoll, viel häufiger zu rendern als zu berechnen (wenn man genügend oft berechnet).



  • Naja, du machst z.B. alle 40ms ein Logikupdate. Zwischen diesen Updates kann ein sich bewegender Ball/Gegner/Gegenstand sich doch einfach mit konstanter Geschwindigkeit weiter fortbewegen. Löst man imho mit Animatoren. Beschleunigungen, Richtungsänderungen, etc. werden dann im nächsten Logik-Update eingeleitet. Dass ein Ball für 40ms 1 cm innerhalb einer Wand war wird wohl niemand bemerken.
    Ausserdem hat man so eine saubere Trennung von Logik und Grafik und man man muss die Geschwindikeiten nicht anpassen (was man bei zeit-basierten Bewegungen sonst machen müsste). Aber die Diskussion hatten wir glaube ich schon ein paar mal.

    Die einzig sinnvolle "Framebremse", die ich kenne, ist V-Sync, aber das nur weil sie optisch unschöne Effekte verhindert.

    Gruß
    Don06



  • Naja den Vsync kann man schön als Bremse hernehmen, so braucht man kein Sleep und keine Busy-Loops.

    p.S.: ich weiss schon dass Vsync oft nicht optimal ist, besonders dann wenn der Rechner zu langsam ist um die volle Framerate (=monitor Refresh) zu schaffen. Aber ich finde es gut wenn man in einem Spiel einstellen kann ob es auf den Vsync warten soll oder nicht -- Leute die einen ausreichend schnellen Rechner haben bekommen dann butterweiche Animationen, ohne unnötig CPU Zeit zu verbraten.


Anmelden zum Antworten