Frage zu Timing, Auswirkungen und Möglichkeiten - Neue Frage
-
Ich beschäftige mich momentan mit Timings um mal einen überblick zu bekommen wie sich Spiele generell Timen lassen und bin dabei Auf einige Fragen gestoßen. Ich habe etwas herumexperimentiert und dabei festgestellt das VSync ja scheinbar unumgänlich ist um saubere, Ruckelfreie Biler zu bekommen.
Wie genau wird Timing in Modernen Spielen eigentlich gelöst? Ich habe gelesen man soll das Rendering vom Rest des Spiels entkopeln, die einzige lösung die ich bisher allerdings gefudnen habe war die zeit zu messen die für einen Frame benötigt wird und anhand dessen eine Bewegung in meinem kleinen Programm anzupassen so das sich ein Objekt das ich bewege immer gleich schnell bleibt egal ob der Rechner High End ist oder eine Gurke. Mir scheint dieses System aber nicht sehr Praktikabel wenn ich zB eine KI aufrufen will die ja immer zu festen Zeiten bestimte Aufgaben erledigt, das würde doch in mehreren Zählern und Timern gipfeln nur um am ende auch eine Gleichmäßige Geschwindigkeit zu haben. Und was mir auch noch Sorgen amcht ist das das VSync ja im Zweifel den das Programm Blockiert bis ein Flip ausgeführt werden kann, und somit gerade auf langsammeren Rechner die Berechnungen zusätzlich verzögert.
Gibt es dafür nicht bessere Praktikablere und vor allem verlässlichere Lösungen?
Eine weitere Frage die sich mir in zusammenhang mit Timern noch stellt ist folgende, ich habe den timer mal eingesetzt um 2 teile des Programms Zeitlich zu messen, der erste teil bestannt aus 3 Blits (2 Bitmaps davon eine so groß wie der Zielscreen, eingelagert im VRAM sowie ein Blit fürs Schwarzzeichnen des Screens) und 2 TextoOuts über die GDI, dauer ca 0,25ms, Teil 2 Bestannt aus einem Flip ohne VSYNC, dauer heir war 1,25ms. Meine Frage dazu ist wieso geht das Kopieren von Offscreen Surfaces und das Zeichnen von Texten schneller als ein Flip von dem ich gelesen habe das dort intern auf der Hardware lediglich die Adresszeiger vertauscht werden?
Danke schonmal im voraus.
-
dazu gab es mal einen thread der eventuell schon alle deine fragen beantworten kann

http://www.c-plusplus.net/forum/viewtopic-var-t-is-21275.html
-
Danke er beantwortet in der Tat etliche Fragen. Aber umd as Kurz zu Rekapitulieren, ich muß vorraussetzen das die Leistung des PCs zumindest ein gewisses Minimum Erfüllt. Ich müsste also Quasi einmal die Zeit nehmen und dann iemr vor der Logikschleife die aktuelle Zeit berechnen und sie mit dem timing vergleichen, wenn die logik anspringt dann das timing umd en gewünschten zeitrahmen erhöhen? Also in etwa so?
Zeit timing; Zeit aktuellezeit; QuerryPerformanceCounter(); //timing und aktuellezeit einmal korrekt einstellen while(true) { //aktuellezeit neu errechnen while(timing<aktuellezeit) { //Logik durchführen timing+wunschzeit;//timing für die nächste rudne einstellen } Rendern(); }Eine weitere Frage die noch offen steht bei mir wäre die anch der Zeitdauer, wieso ist das Blitten so schnell wärend das Flipen so lange dauert, obwohl der Blitter kopiert, beim Flip aber nur Adressen getauscht werden?
-
Gut funktioniert, ich verstehe auch den Anhang mit den Animatoren, hat dazu aber evtl jemand noch nen weiterführenden link wo amn sichd as mal durchlesen kann, ich werde hier leide rnicht wirklich fündig.
-
Vonwegen Mindestleistung voraussetzen: wenn es kein Online-Spiel ist, dann gibt's ne relativ einfache Lösung: du limitierst die maximale Delta-Time.
Also wenn zwischen 2 Frames 10 Sekunden vergangen sind, dann "tust du so" als obs in wirklichkeit nur 100ms oder 200ms oder so gewesen wären.Natürlich läuft das Spiel dann langsamer sobald diese "Deckelung" greift, aber du vermeindest dadurch den Fall dass es von Frame zu Frame immer länger dauert die Logik zu rechnen, weil der Computer eben nichtmal die Logik in Echtzeit hinbekommt.
Was das Blit vs. Flip angeht: mit welcher API machst du das denn? Wenn du Direct3D verwendest können viele Dinge die du der Grafikkarte anschaffst in eine Queue gestellt und später abgearbeitet werden. Wirklich warten bis alles fertig gezeichnet ist muss Direct3D dann natürlich bevor das Bild angezeigt wird, also in PresentImage. Dadurch ist es oft so dass die ganzen render Calls kaum Zeit brauchen, PresentImage aber dafür recht lange braucht.
-
hustbaer schrieb:
Vonwegen Mindestleistung voraussetzen: wenn es kein Online-Spiel ist, dann gibt's ne relativ einfache Lösung: du limitierst die maximale Delta-Time.
Also wenn zwischen 2 Frames 10 Sekunden vergangen sind, dann "tust du so" als obs in wirklichkeit nur 100ms oder 200ms oder so gewesen wären.Natürlich läuft das Spiel dann langsamer sobald diese "Deckelung" greift, aber du vermeindest dadurch den Fall dass es von Frame zu Frame immer länger dauert die Logik zu rechnen, weil der Computer eben nichtmal die Logik in Echtzeit hinbekommt.
Was das Blit vs. Flip angeht: mit welcher API machst du das denn? Wenn du Direct3D verwendest können viele Dinge die du der Grafikkarte anschaffst in eine Queue gestellt und später abgearbeitet werden. Wirklich warten bis alles fertig gezeichnet ist muss Direct3D dann natürlich bevor das Bild angezeigt wird, also in PresentImage. Dadurch ist es oft so dass die ganzen render Calls kaum Zeit brauchen, PresentImage aber dafür recht lange braucht.
Ich benutze nur DDraw.
So einen Deckel will ich eigentlich nicht draufbauen, mein Ziel ist es ja das das ganze bei jeem im selben Speed abläuft, also werde ich wohl voirraussetzenw enn ich am ende 30-40FPS habe mit meinem älfteren rechner das andere Leute dann auch 15-10 Schaffen. Momentan ist mein letztes Verbliebenes Problem ohnehin die Animation, ich bastel hier ja etwas mit einem kleinen programm herum das ein Quadrat Zeichnet und mit 25FPS die Tastatureingaben holt und den würfel bewegt, leider springt er dabei da mehrere Frames gleich sind und ich finde im moment noch keinen Lösungsansatz der die bewegung auf Frames verteilt und mich zufriedenstellt.
-
Nah einigen basteleien habe ich einen guten Ansatz gefunden der meinem Quadrat zu flüssiger Bewegung verhiflt, allerdings stimmt da noch irgendetwas nicht so ganz, hier ist ein Pseudocode wie ichd as ganze aufgebaut habe:
int logicschleife; //beide über QueryPerformanceCounter als angabe mit 1=1ms int aktuellezeit; while(true)//Schleife für Windowsnachrichten, Rendern, logic usw { Windowsnachrichten(); Logicschleife { //aktuelel zeit hier holen if(logicschleife<aktuellezeit) //abfrage ob genug zeit vergangen ist um logicschleife auszuführen { if(logicschleife+40<aktuellezeit) //hier errechnen falls mehr als eine //logicschleife hinetreinander kommen würde, durch niedrige fps else //hier angeben das die logicshcleife nur 1x ausgeführt wird Tastenabfragen(); //hier bewegungsgeschwindigkeit anpassen, falls mehr als eine //logicschleife komemn solte um bewegung pro frame zu beschleunigen //hier errechnen wieviel fps bis zur nächsten logicschleife kommen //würden und somit die geschwindigkeit pro frame einstellen }; }; Rendern();//hier wird die geschwindigkeit pro frame genutzt um die aktuelle //position des Quadrates anzugeben };Das ganze funktioniert auch, die Sache hat nur einen haken, das Quadrat macht gelegentlich einen ruck, dh es bewegt sich flüssig dann kommt ein ruck als wenn es mehrere frames überspringt, ich habe einen counter geadded und die Framezahl die in der Logicerrechnet wird stimmt +-2 mit der tatsächlichen fps überein, dennoch ist auf allen Rechnern der ruck zu sehen, auf langsammen tritt er sogar etwas häufiger auf, das ganze ist komplett zufällig, ich hatte es auch versucht anhand der FPS einmal pro Sekunde den Speed pro Frame des Quadrats neu zu berechnen, statt den Speed pro logic auf die nächsten frames zu verteilen, leider brachte das auch keinen Erfolg. Hat da evtl jemand eine Idee woran das liegen könnte?