Gleitender Durchschnitt Fps


Sie benötigen einen geglätteten Durchschnitt, der einfachste Weg ist, die aktuelle Antwort zu nehmen (die Zeit, um das letzte Bild zu zeichnen) und kombinieren Sie es mit der vorherigen Antwort. Durch Einstellen des 0,9 0,1-Verhältnisses können Sie die Zeitkonstante ändern - so schnell reagiert die Zahl auf Änderungen. Ein größerer Bruchteil zugunsten der alten Antwort ergibt eine langsamere glattere Veränderung, ein großer Bruchteil zugunsten der neuen Antwort gibt einen schnelleren sich ändernden Wert. Offensichtlich müssen die beiden Faktoren hinzufügen, um eine beantwortet Sep 17 08 um 20:33 Aber, wie Sie darauf hinweisen, theres eine Menge von Variationen in der Zeit, es braucht, um ein einziges Bild zu machen, und aus einer Benutzeroberfläche Perspektive Aktualisierung der fps Wert an der Frame-Rate ist überhaupt nicht nutzbar (es sei denn, die Zahl ist sehr stabil). Was Sie wollen ist wahrscheinlich ein gleitender Durchschnitt oder eine Art von Binning-Reset Zähler. Beispielsweise können Sie eine Warteschlangen-Datenstruktur pflegen, die die Rendering-Zeiten für jedes der letzten 30, 60, 100 oder What-Have-You-Frames hielt (Sie könnten es sogar so konzipieren, dass das Limit zur Laufzeit einstellbar war). Um eine anständige fps-Näherung zu bestimmen, können Sie die durchschnittlichen fps aus allen Renderzeiten in der Warteschlange bestimmen: Wenn Sie das Rendering eines neuen Frames beenden, geben Sie eine neue Renderzeit ein und löschen eine alte Renderzeit. Alternativ können Sie nur dann dequeue, wenn die Summe der Renderzeiten einen voreingestellten Wert überschritten hat (z. B. 1 Sekunde). Sie können den letzten fps-Wert und einen zuletzt aktualisierten Zeitstempel beibehalten, so dass Sie auslösen können, wann die fps-Abbildung aktualisiert werden soll, wenn Sie dies wünschen. Obwohl mit einem gleitenden Durchschnitt, wenn Sie konsistente Formatierung haben, würde das Drucken der momentanen durchschnittlichen fps auf jedem Frame wahrscheinlich ok sein. Eine andere Methode wäre, einen Rücksetzzähler zu haben. Pflegen Sie einen genauen Zeitstempel (Millisekunde), einen Bildzähler und einen fps-Wert. Wenn Sie das Rendering abgeschlossen haben, erhöhen Sie den Zähler. Wenn der Zähler einen voreingestellten Grenzwert erreicht hat (zB 100 Frames), oder wenn die Zeit seit dem Zeitstempel einen voreingestellten Wert überschritten hat (zB 1 Sekunde), berechnen Sie die fps: Setzen Sie dann den Zähler auf 0 zurück und setzen Sie den Zeitstempel auf aktuelle Uhrzeit. Es gibt mindestens zwei Möglichkeiten, es zu tun: Die erste ist die eine andere haben hier vor mir erwähnt. Ich denke sein die einfachste und bevorzugte Weise. Sie müssen nur verfolgen, wie viele Frames Sie timestart gerendert haben: die Zeit seit dem Beginn der Counting-Zeit: die aktuelle Zeit Die Berechnung der fps ist in diesem Fall so einfach wie die Auswertung dieser Formel: FPS cn (timenow - timestart). Dann gibt es die uber cool Art und Weise können Sie gerne einen Tag zu verwenden: Lets sagen, Sie haben i Frames zu prüfen. Ich benutze diese Schreibweise: f0, f1. Fi-1, um zu beschreiben, wie lange es dauerte, um Frame 0, Frame 1. Frame (i-1) zu rendern. Dann, mathematische Definition von fps nach i Frames wäre Und die gleiche Formel aber nur unter Berücksichtigung i-1 Frames. Nun besteht der Trick darin, die rechte Seite der Formel (1) so zu modifizieren, daß sie die rechte Seite der Formel (2) enthält und sie für ihre linke Seite ersetzt. Wie so (sollten Sie es klarer sehen, wenn Sie es auf ein Papier schreiben): Also nach dieser Formel (meine Mathematik Ableitung Geschick sind ein bisschen rostig aber), um die neuen fps zu berechnen müssen Sie wissen, die fps aus dem vorherigen Frame , Die Dauer, die zum Rendern des letzten Frames und der Anzahl der gerenderten Frames benötigt wurde. Dies könnte Overkill für die meisten Menschen, das ist, warum ich es nicht gepostet hatte, wenn ich es implementiert. Aber es ist sehr robust und flexibel. Es speichert eine Warteschlange mit den letzten Frame-Zeiten, so kann es genau berechnen einen durchschnittlichen FPS-Wert viel besser als nur den letzten Frame in Erwägung ziehen. Es erlaubt Ihnen auch, einen Rahmen zu ignorieren, wenn Sie etwas tun, dass Sie wissen, wird künstlich verschrauben, dass Frames Zeit. Darüber hinaus können Sie die Anzahl der Frames zu ändern, um in der Warteschlange zu speichern, wie es läuft, so können Sie es testen, on the fly, was der beste Wert für Sie ist. Beantwortet Mai 23 13 am 19:41 Gute Antworten hier. Wie Sie es implementieren, hängt davon ab, wofür Sie es brauchen. Ich bevorzuge den laufenden Durchschnitt ein selbst Zeit Zeit 0.9 lastframe 0.1 durch den Kerl oben. Aber ich persönlich gerne meine durchschnittlich stärker zu neueren Daten Gewicht, weil in einem Spiel ist es SPIKES, die am härtesten zu Squash und damit von Interesse für mich sind. Also ich würde etwas mehr wie ein .7 verwenden. 3 Split wird ein Spike zeigen, um viel schneller (obwohl sein Effekt wird Drop off-Bildschirm schneller als auch unten sehen) Wenn Ihr Fokus auf RENDERING Zeit ist, dann die .9.1 Split Arbeitet ziemlich nett bc es neigen dazu, mehr glatt. Obwohl für GameplayAIphysics Spikes sind viel mehr ein Anliegen als das wird in der Regel, was macht Ihr Spiel aussehen choppy (was oft schlechter als eine niedrige Framerate Annahme waren nicht Tauchen unter 20 fps) Also, was ich tun würde, ist auch so etwas hinzufügen : (Füllen Sie 3.0f mit welcher Größe Sie finden, um eine unannehmbare Spitze zu sein) Dieses lässt Sie finden und so lösen FPS-Ausgaben das Ende des Rahmens, den sie geschehen. Beantwortet November 13, 2008 um 22:56 Uhr Ich mag die Zeit 0,9 lastframe 0,1 durchschnittliche Berechnung, die das Display wechselt reibungslos. Ndash Fabien Quatravaux Sie konnten einen Zähler halten, ihn inkrementieren, nachdem jeder Rahmen gerendert wurde, dann setzen Sie den Zähler zurück, wenn Sie auf einer neuen Sekunde sind (das Speichern des vorherigen Wertes als die letzten Sekunden der übertragenen Rahmen) In ( C like) Pseudocode diese beiden sind, was ich in industriellen Bildverarbeitung Anwendungen, die zu verarbeiten hatte Bilder aus einer Reihe von extern getriggerten Kameras. Variationen der Bildrate hatten eine andere Quelle (langsamer oder schneller Produktion auf dem Band), aber das Problem ist das gleiche. (Ich nehme an, dass Sie einen einfachen timer. peek () - Aufruf haben, der Ihnen etwas wie die nr von msec (nsec) seit dem Anwendungsstart oder dem letzten Aufruf gibt) Lösung 1: schnell aber nicht jedes Frame aktualisiert Solution 2: Erfordert mehr Speicher und CPU geantwortet Antwort # 3 am: Mai 13, 2010, 07:12:39 am »Es ist viel besser als mit einer großen Anzahl von alten Framerates ist nur so etwas wie dies zu tun: Diese Methode verwendet weit weniger Speicher, erfordert weit weniger Code und legt mehr Wert auf die jüngsten Framerate als alte Framerate, während noch Glättung der Auswirkungen der plötzlichen Framerate Veränderungen. Antwort # 2 am: Mai 16, 2010, um 12:01 Uhr Ihre Antwort 2017 Stack Exchange, IncA Detaillierte Erklärung der JavaScript-Spiel Loops und Timing Die Hauptschleife ist ein Kernteil jeder Anwendung, in der Zustand ändert sich im Laufe der Zeit. Bei Spielen wird die Hauptschleife oft als Spielschleife bezeichnet. Und es ist typischerweise verantwortlich für die Berechnung von Physik und AI sowie das Zeichnen des Ergebnisses auf dem Bildschirm. Leider ist die überwiegende Mehrheit der Hauptschleifen online gefunden - vor allem in JavaScript - aufgrund von Zeitproblemen falsch geschrieben. Ich sollte wissen, dass ich meinen fairen Anteil an schlechten geschrieben habe. Dieser Beitrag soll zeigen, warum viele Hauptschleifen behoben werden müssen und wie man eine Hauptschleife korrekt schreibt. Wenn youd eher überspringen die Erklärung und nur den Code, es richtig zu machen. Können Sie mein Open-Source-Projekt MainLoop. js verwenden. Ein erster Versuch würde ein Spiel schreiben. Der Einfachheit halber wollten wir nur einen schwingenden Kasten zeichnen: Lasst es uns zeigen: Okay, das war nicht so schlimm. Jetzt können Gerüste die JavaScript-Anwendung. Zuerst benötigt unsere Box einige Eigenschaften, um ihre Position und Geschwindigkeit zu bestimmen. Lets auch in eine Funktion, draw () werfen. Um die Boxen neue Position anzuzeigen: Jetzt die Spiele-Logik. Wir wollen, dass die Box hin und her bewegt, so gut fügen Sie einfach die Geschwindigkeit auf die Position. Dies ist, wo die Dinge schief gehen, wie youll sehen in einem Moment. Und jetzt lässt es laufen. Um dies zu tun, benötigen wir eine Schleife, die gerade die Ausführung der update () - Funktion hält, um die Box zu verschieben, und dann die draw () - Funktion, um die Visualisierung auf dem Bildschirm zu aktualisieren. Wie sollten wir das tun? Wenn Sie jemals Spiele in einer anderen Sprache geschrieben haben, denken Sie vielleicht an eine while-Schleife: Javascript ist jedoch single-threaded, was bedeutet, dass dieser Ansatz den Browser daran hindert, fast alles andere auf dieser Seite zu tun. Als Ergebnis wird der Browser sperren, und nach ein paar Sekunden wird es dem Benutzer einen Fehler zu fragen, ob sie Ihr Skript beenden möchten. Youll wollen, dass Ihr Spiel für mehr als ein paar Sekunden laufen, so das ist nicht gut Wir brauchen einen Weg, um die Kontrolle aus dem Spiel Loop zurück zu dem Browser für eine Weile, bis der Browser ist bereit für uns wieder Arbeit zu tun. Wenn Sie mit JavaScript vertraut sind, denken Sie vielleicht an setTimeout () oder setInterval () - Funktionen, die das Ausführen von Code nach einer bestimmten Zeit erlauben. Dies ist eine ziemlich vernünftige Idee, aber in Browsern Theres ein besserer Weg: requestAnimationFrame (). Es ist eine ziemlich neue Funktion mit starken Browser-Unterstützung (zum Zeitpunkt des Schreibens, alle Browser außer IE9 und unten unterstützen es). Sie übergeben einen Rückruf an diese Funktion, und es läuft, dass Rückruf das nächste Mal der Browser ist bereit, um zu ändern, wie die Seite aussieht. Auf einem 60-Hz-Monitor bedeutet dies, dass eine optimal abgestimmte Anwendung 60 Mal pro Sekunde Updates (sog. Malerahmen) zeichnen kann. Also, Ihre Hauptschleife hat 1 60 16.667 Millisekunden, um seine Sache zu tun, jedes Mal, wenn es läuft, wenn Sie wollen, dass 60 Frames pro Sekunde ideal schlagen. Nun abdecken eine Polyfill für node. jsio. js und kleineren Browsern später. Beachten Sie, dass die meisten Monitore nicht mehr als 60 Bilder pro Sekunde (FPS) anzeigen können. Ob der Mensch den Unterschied unter den hohen Bildraten erkennen kann, hängt von der Anwendung ab, aber als Referenz wird der Film gewöhnlich bei 24 FPS, andere Videos bei 30 FPS angezeigt, die meisten Spiele sind über 30 FPS akzeptabel und die virtuelle Realität kann 75 FPS fühlen natürlich. Einige Gaming-Monitore gehen bis zu 144 FPS. Alright, verwenden Sie requestAnimationFrame (), um die Hauptschleife zu schreiben Es ist wichtig, dass draw () aufgerufen wird, nachdem update (), weil wir wollen, dass der Bildschirm einen Zustand der Anwendung, die so aktuell ist wie möglich zu reflektieren. (Beachten Sie, dass Canvas-basierte Anwendungen möglicherweise darauf achten, den ersten Frame in den ursprünglichen Zustand der Anwendungen zu zeichnen, bevor irgendwelche Updates aufgetreten sind. Ein Ansatz, dies zu tun, wird später in diesem Artikel diskutiert.) Einige Beiträge im Internet spekulieren, dass Rendering früher im RequestAnimationFrame-Callback kann der Bildschirm schneller gemalt werden, das ist meistens nicht wahr, und selbst wenn es ist, ist es normalerweise nur ein Kompromiss zwischen dem Rendern des aktuellen Frames früher und dem Rendering des nächsten Frames später. Es spielt keine Rolle, wenn requestAnimationFrame erneut aufgerufen wird, weil nur ein Frame auf einmal ausgeführt werden kann, aber ich finde, dass es den logischsten Sinn macht, einen anderen Frame anzufordern, sobald der aktuelle abgeschlossen ist. Timing-Probleme Bisher hat unsere update () - Funktion das Problem, dass es von der Frame-Rate abhängig ist. In anderen Worten, wenn Ihr Spiel langsam (dh weniger Frames pro Sekunde) ausgeführt wird, wird Ihr Objekt auch langsam verschoben, während, wenn Ihre Anwendung schnell ausgeführt wird (das heißt, mehr Frames pro Sekunde), Ihr Objekt wird angezeigt Schnell zu bewegen. Solche unvorhersehbaren Gameplay-Erlebnisse zu haben, ist vor allem bei Multiplayer-Spielen unerwünscht. Niemand will ihren Charakter zu einem langsamen, nur weil ihr Computer ist nicht so mächtig. Sogar in Einzelspieler-Spielen beeinflusst die Geschwindigkeit erheblich Schwierigkeiten: Spiele, die schnelle Reaktionen erfordern, werden bei langsamen Geschwindigkeiten einfacher und bei schnellen Geschwindigkeiten unspielbar schwierig. Um dies für uns selbst zu sehen, können wir die Fähigkeit zur Drosselung des FPS hinzufügen. Nutzen Sie die Tatsache, dass requestAnimationFrame () einen Zeitstempel an den Callback übergibt. Jedes Mal, wenn die Schleife läuft, überprüfen Sie, ob eine minimale Menge an Zeit verstrichen ist, wenn es hat, gut machen den Rahmen, und wenn es hasnt, gut nur für den nächsten Frame warten. Sie können sehen, wie viel schmerzhaft langsamer es ist: Wir müssen es besser machen. Das Problem ist, dass unsere Anwendung nicht an Echtzeit gebunden ist. Wie können wir fix, dass Als ein erster Durchlauf versuchen, Multiplikation der Geschwindigkeit durch die Menge der Zeit, die zwischen Rendering-Frames, die gut nennen Delta übergeben hat. Also, statt boxPos boxVelocity gut laufen stattdessen laufen boxPos boxVelocity Delta. Nun müssen wir unsere Update-Funktion anpassen, um delta als Parameter aus der Hauptschleife zu erhalten: Ziemlich gute Ergebnisse Unsere Box scheint nun eine konstante Distanz über die Zeit zu bewegen, unabhängig von der Framerate. Wenn seine nicht so verhalten, wie Sie erwarten. Gut, lesen Sie weiter. Physikprobleme Versuchen Sie, die Geschwindigkeit auf einen Wert wie 0,8 aufzuladen. Innerhalb von nur wenigen Sekunden bemerken Sie, dass sich die Box unregelmäßig verhält und eventuell außerhalb des sichtbaren Fensters liegt. Das ist nicht passieren Was schief gegangen ist, ist, dass, während vor der Box bewegt einen konstanten Abstand jedes Bild, jetzt die Box bewegt sich variierende Abstände in jedem Frame - und einige dieser Abstände sind ziemlich groß. In Spielen kann dieses Phänomen es Spielern ermöglichen, durch Wände zu laufen oder sie daran zu hindern, über Hindernisse zu springen. Ein zweites Problem besteht darin, daß kleinere Rundungsfehler, die sich aus der Multiplikation der Geschwindigkeit mit dem Rahmen-Delta ergeben, weil die Schachtel einen variierenden Abstand jedes Rahmens bewegt, zu einer Verschiebung der Schachtelposition im Laufe der Zeit führen wird. Niemand wird in der Lage, genau das gleiche Spiel zu spielen, weil ihre Frameraten sind anders und das wird verschiedene Rundungsfehler verursachen. Das klingt unwesentlich, aber in der Praxis kann es nach nur wenigen Sekunden auch bei normalen Bildraten sichtbar sein Das ist nicht nur schlecht für die Spieler - es ist auch schlecht für den Test, weil wed wie unser Programm genau das gleiche Ergebnis produzieren, wenn wir es geben Gleichen Eingang. Das heißt, wir wollen, dass unser Programm deterministisch ist. Eine Lösung Die wichtigste Erkenntnis zur Festlegung unserer physikalischen Probleme ist, dass wir das Beste aus beiden Welten wollen: Wir wollen eine konstante Menge an Spielzeit simulieren, jedes Mal wenn wir unsere Updates laufen, und doch müssen wir die tatsächliche verstrichene Zeit jeder simulieren Rahmen. Es stellt sich heraus, dass wir beides machen können, indem wir unsere Updates mehrmals mit einem festen Delta laufen lassen, bis wir die ganze Zeit simuliert haben. Lets zwicken unsere Hauptschleife: Alles, was wir taten, ist wir getrennt die Höhe der Zeit in jedem update () von der Zeit zwischen den Bildern simuliert. Unsere update () - Funktion muss nicht geändert werden, wir müssen nur das Delta ändern, das wir an sie übergeben, damit jedes update () eine feste Zeitdauer simuliert. Die Funktion update () wird nun mehrmals pro Frame ausgeführt, um die Gesamtzeit, die seit dem letzten Frame verstrichen ist, zu simulieren. (Wenn die Zeit, die seit dem letzten Frame vergangen ist, kleiner als die feste Simulationszeit ist, führen wir nur eine Aktualisierung () bis zum nächsten Frame aus. Wenn es unsimulierte Zeit gibt, die weniger ist als unsere timetep, Die im nächsten Frame simuliert werden müssen. Daher müssen wir zu delta hinzufügen, anstatt es zuzuweisen - weil wir die übrig gebliebene Zeit aus dem letzten Frame halten müssen.) Dieser Ansatz vermeidet uneinheitliche Rundungsfehler und stellt sicher, dass es keine gibt Riesige Sprünge durch Wände zwischen Rahmen. Lets sehen es in Aktion: Wenn Sie tweak die boxVelocity youll sehen, dass unsere Box nun richtig bleibt, wo es sein soll. Nice Eine Anmerkung: die Wahl des Wertes für unsere timestep war nicht willkürlich. Der Nenner verschwindet effektiv die Frames pro Sekunde, die Benutzer wahrnehmen können (es sei denn, die Zeichnung wird interpoliert, wie unten beschrieben). Eine Verringerung der Zeitspanne erhöht das maximale wahrgenommene FPS auf Kosten eines laufenden Updates () mehrmals pro Vollbild, wenn das tatsächliche FPS niedriger als das Maximum ist. Da das Ausführen von update () mehr Zeit in Anspruch nimmt, dauert es mehr Zeit zu verarbeiten, kann dies tatsächlich verlangsamen die Framerate. Wenn es zu viel verlangsamt, könnte es zu einer Spirale des Todes führen. Panic Spirale des Todes Leider, noch einmal weve eingeführt ein neues Problem. In unserem ersten Versuch, wenn Frames dauerte eine lange Zeit zu aktualisieren und zu rendern, die Framerate nur verlangsamt, bis jeder Frame dauerte lange genug für die Updates auftreten. Allerdings sind unsere Updates abhängig von der Zeit jetzt. Wenn ein Rahmen eine lange Zeit dauert, um zu simulieren, muss der nächste eine noch längere Zeit simulieren. Das bedeutet, dass update () mehrmals ausgeführt werden muss, was bedeutet, dass unser neuer Frame noch länger dauern wird, um zu simulieren, und so weiter. Bis die Anwendung einfriert und abstürzt. Dies nennt man eine Spirale des Todes. Nicht gut. Im Allgemeinen waren fein, solange unser timestep auf einen Wert eingestellt ist, der hoch genug ist, dass die Updateaufrufe in der Regel weniger Zeit benötigen als die Zeit, die sie simulieren. Dies ist jedoch für verschiedene Hardware - und Workloads unterschiedlich. Plus, das ist JavaScript zu reden: wir haben sehr wenig Kontrolle über die Ausführungsumgebung. Wenn der Benutzer auf eine andere Registerkarte wechselt, stoppt der Browser die Bilderrahmen, und am Ende mit viel Zeit zu simulieren, wenn der Benutzer zurück kommt. Wenn seine zu viel Zeit, wird der Browser hängen. Sanity Check Wir brauchen einen Fluchtweg. Fügen Sie einen Sanity-Check zu unserem Update-Schleife: Was sollten wir tun, in unserem Panik-Funktion Nun, das hängt davon ab. Turn-basierte Multiplayer-Spiele verwenden eine Networking-Technik namens lockstep, die dafür sorgt, dass alle Spieler das Spiel im gleichen Tempo erleben. Das bedeutet, dass alle Spieler das Spiel im Tempo des langsamsten erleben. Wenn ein Spieler zu lange zurückfällt, wird dieser Spieler fallen gelassen, so dass die anderen Spieler nicht nach unten gezogen werden. Also, in lockstep Spiele, wird der Spieler nur fallen gelassen. In Multiplayer-Spielen, die nicht verwenden lockstep, wie erste Person Schützen, gibt es in der Regel einen Server, der einen autoritativen Zustand des Spiels hat. Das heißt, der Server empfängt alle Spieler Eingänge und berechnet, was die Welt aussehen sollte, um zu verhindern, dass Spieler von Betrug. Wenn ein Spieler zu weit weg von dem autoritativen Zustand driftet, wie es der Fall in einer Panik wäre, dann muss der Spieler wieder in den autoritativen Zustand zurückgebracht werden. (In der Praxis ist dies desorientiert, so dass der Spieler zurückgreifen kann auf eine temporäre alternative Update-Funktion, die die Client-Welt zurück in Richtung der Server-Welt reibungsloser erleichtern wird.) Sobald wir den Benutzer auf ihren neuen Zustand Snap wir dont wollen sie Noch haben eine Menge Zeit übrig, um zu simulieren, weil wir effektiv schnell-weitergeleitet durch sie. So können wir es loswerden: Wenn der Server dies tut, würde es nichtdeterministische Verhalten einführen, aber nur der Server braucht das Spiel, um deterministisch so seine feine auf dem Client in einem vernetzten Spiel vorzugehen. In Einzelspieler-Spielen kann es zulässig sein, die Anwendung für eine Weile laufen zu lassen, um zu sehen, ob sie aufholen wird. Allerdings könnte dies auch dazu führen, dass die Anwendung aussehen, wie es läuft sehr schnell für ein paar Frames, wie es Übergänge durch die Zwischenzustände. Eine Alternative, die akzeptabel sein kann, besteht darin, einfach die nichtimimierte verstrichene Zeit zu ignorieren, wie wir oben in dem vernetzten Nicht-Lockstep-Fall getan haben. Auch dies führt zu nicht-deterministischen Verhalten, aber Sie können entscheiden, dass eine Panik ist ein außergewöhnlicher Umstand und alle Wetten ausgeschaltet sind. In allen Fällen, wenn die Anwendung Panik häufig und ihre nicht wegen der in einem Hintergrund Registerkarte, ist dies wahrscheinlich ein Hinweis, dass die Hauptschleife zu langsam ausgeführt wird. Sie können Ihre Zeitstep erhöhen. FPS-Steuerung Eine komplementäre Methode zur Verhinderung von Todesverletzungen (und niedrigen Bildraten im Allgemeinen) besteht darin, die Bildrate zu überwachen und die Aktivitäten, die in der Hauptschleife auftreten, einzustellen, wenn die Bildrate zu niedrig wird. Oft wird ein Rückgang der Bildrate wahrscheinlich spürbar sein, bevor eine Panik auftritt, so dass wir Panik verhindern können, indem wir vorbereitet werden. Es gibt viele Möglichkeiten, die Bildrate zu verfolgen. Eine Möglichkeit ist, zu verfolgen, wie viele Frames wurden in jeder Sekunde für eine gewisse Zeit (sagen wir, die letzten 10 Sekunden) gerendert und durchschnittlich. Allerdings ist das ein wenig mehr Performance-intensive als wed wie, und es wäre schön, den Durchschnitt auf die jüngsten Sekunden zu gewichten. Ein einfacherer Ansatz, der diese Gewichtung ausführt, ist die Verwendung eines exponentiellen gleitenden mittleren FPS in unserer Hauptschleife: Der 0,25 ist ein Zerfallsparameter - es ist im Wesentlichen, wie stark jüngere Sekunden gewichtet werden. Die fps-Variable enthält nun unsere geschätzten Frames pro Sekunde. Groß. Jetzt, was sollten wir mit ihm tun, ist die offensichtliche Sache zu tun, ist es zu zeigen: Wir können die FPS in mehr nützliche Möglichkeiten verwenden. Wenn es zu niedrig ist, können wir das Spiel beenden, die visuelle Qualität verringern, Aktivitäten außerhalb der Hauptschleife beenden oder reduzieren, wie Eventhandler oder Audiowiedergabe, nicht kritische Updates weniger häufig durchführen oder die Zeitstep erhöhen. (Beachten Sie, dass diese letzte Option mehr Zeit pro Update () - Aufruf simuliert, was dazu führt, dass sich die Anwendung nicht-deterministisch verhält, so dass sie sparsam eingesetzt werden sollte.) Wenn das FPS wieder hochgeht, können wir diese umkehren Maßnahmen. Anfänge und Endungen Es kann nützlich sein, Funktionen zu haben, die Ihre Hauptschleife am Anfang und am Ende der Schleife anruft (nennen sie begin () bzw. end () für Setup und Cleanup. Im Allgemeinen ist begin () nützlich für die Verarbeitung von Eingaben, bevor die Updates ausgeführt werden (zum Beispiel Laichprojektile, wenn der Spieler die Feuerwaffen-Taste drückt). Wenn es langwierige Aktionen gibt, die als Reaktion auf die Benutzereingabe ergriffen werden müssen, können die Verarbeitungen in Chunks in der Hauptschleife anstelle von allen auf einmal in den Ereignisbehandlungsroutinen nützlich sein, um Verzögerungen von Frames zu vermeiden. Die end () - Funktion ist auch nützlich für die schrittweise Ausführung lang anhaltender Updates, die arent zeitsensitiv sind, sowie für die Anpassung an Änderungen in FPS. Einen Zeitstep auswählen Im Allgemeinen ist 1000 60 eine gute Wahl für die meisten Fälle, weil die meisten Monitore bei 60 Hz laufen. Wenn Sie feststellen, dass Ihre Anwendung sehr leistungsintensiv ist, können Sie sie auf zB 1000 30 einstellen. Dies wirkt sich effektiv auf Ihre wahrnehmbare Bildrate bei 30 FPS aus (sofern die Zeichnung nicht wie unten beschrieben interpoliert wird). Beachten Sie, dass Frames abhängig von Ihrem Monitor und Grafiktreiber gedrosselt werden können, so dass das Maximum, das Sie einstellen, nicht das Maximum ist, das Sie in der Praxis erhalten. Wenn Ihr Spiel schnell läuft und Sie genauere Simulationen wollen, können Sie maximale FPS-Werte von High-End Gaming-Bildschirme: 75, 90, 120 und 144. Viel darüber hinaus und youll am Ende verlangsamt sich. Performance-Überlegungen Wenn Ihre Leistung ist nicht so gut wie youd wie es zu sein, interpolierende Zeichnung und mit Web-Arbeitnehmer sind zwei strukturelle Veränderungen können Sie, dass eine solide Wirkung haben können. Interpolieren Zeichnung Nachdem unsere Updates beendet zu laufen, wird es in der Regel einige Zeit übrig bleiben in Delta, die weniger als eine volle timetep ist. Das Übergeben des Prozentsatzes eines timetep, das noch nicht der draw () - Funktion simuliert wurde, erlaubt es, zwischen Frames zu interpolieren. Diese visuelle Glättung verringert das Stottern selbst bei hohen Bildraten. Stottern tritt auf, weil die Zeit, die durch update () und die Zeit zwischen draw () - Aufrufen simuliert wird, normalerweise unterschiedlich ist. Um zu veranschaulichen, ob update () die Simulation an jeder vertikalen Leiste in der ersten Zeile weiter vornimmt, und draw () - Aufrufe an jeder vertikalen Leiste in der zweiten Zeile darunter auftreten, dann haben einige Frames Zeit übrig, die noch nicht simuliert wird Update () beim Rendern in draw (): Damit draw () die Bewegung für Rendering-Interpolation interpoliert, müssen die Objekte nach der letzten update () beibehalten und zur Berechnung eines Zwischenzustandes verwendet werden. Beachten Sie, dass dies bedeutet, rendert wird bis zu einem Update () hinter sich. Dies ist immer noch besser als extrapolieren (Projektionsobjekte Zustand nach einem zukünftigen Update ()), die bizarre Ergebnisse erzeugen können. Das Speichern von mehreren Zuständen kann schwierig einzurichten sein und bedenken, dass das Ausführen dieses Prozesses Zeit braucht, die die Bildrate nach unten drücken könnte, so dass es sich nicht lohnt, wenn das Stottern nicht sichtbar ist. Heres, wie wir Interpolation für unsere Box implementieren können: Verwenden Sie Web Workers für Updates Wie bei allem in der Hauptschleife beeinflusst die Laufzeit von update () direkt die Frame-Rate. Wenn update () lange genug dauert, bis die Bildrate unter die Zielbildrate (Budgeted) fällt, können Teile der update () - Funktion, die nicht zwischen jedem Frame ausgeführt werden müssen, in Web Workers verschoben werden. (Verschiedene Quellen im Internet schlagen manchmal andere Scheduling-Muster mit setTimeout () oder setInterval () vor. Diese Ansätze bieten manchmal bescheidene Verbesserungen mit minimalen Änderungen an vorhandenem Code, aber da JavaScript einfaches Thread ist, blockieren die Updates weiterhin das Rendering und ziehen nach unten Die Frame-Rate. Mit Web Workers ist mehr Arbeit, aber sie führen in separaten Threads, so dass sie mehr Zeit in der Hauptschleife freigeben.) Eine nicht erschöpfende Liste der Dinge zu denken, wenn youre unter Berücksichtigung der Verwendung von Web Workers: Profil Ihres Codes Bevor Sie die Arbeit, um es in Web Workers bewegen. Es könnte das Rendering sein, das der Engpass ist, wobei in diesem Fall die erste Lösung darin besteht, die visuelle Komplexität der Szene zu verringern. Es macht keinen Sinn, den gesamten Inhalt von update () in Arbeitnehmer zu verschieben, es sei denn, Ihre draw () - Funktion kann zwischen Frames interpolieren, wie oben diskutiert. Die niedrigste hängende Frucht, die aus update () herausgezogen wird, ist Hintergrundaktualisierungen (wie Berechnen des Bürgerglühens in einem Stadtgebäudespiel), Physik, die die Szene nicht beeinflusst (wie Flaggen, die im Wind wellen) und alles, was okkludiert oder geschieht Weit weg vom Bildschirm. Wenn draw () die Physik basierend auf der Aktivität, die in einem Worker auftritt, interpolieren muss, muss der Worker den Interpolationswert zurück an den Hauptthread übergeben, so dass is für draw () verfügbar ist. Web-Worker können nicht auf den Zustand des Haupt-Threads, so dass sie nicht direkt ändern können Objekte in Ihrer Szene. Das Verschieben von Daten zu und von Web Workers ist ein Schmerz. Der schnellste Weg, dies zu tun, ist mit übertragbaren Objekten: Grundsätzlich können Sie einen ArrayBuffer an einen Arbeiter weitergeben und dabei die ursprüngliche Referenz zerstören. Weitere Informationen zu Web Workers und Transferable Objects finden Sie unter HTML5 Rocks. Starten und Stoppen Bisher, sobald unser Spiel begann die Hauptschleife, wir havent hatte eine Möglichkeit, es zu stoppen. Mit den Funktionen start () und stop () können Sie verwalten, ob die Anwendung ausgeführt wird. Das erste, was wir tun müssen, ist herauszufinden, wie zu stoppen Anfrage Frames. Eine Möglichkeit wäre, eine laufende Boolesche Variable zu behalten, die steuert, ob die Hauptschleife requestAnimationFrame () erneut aufruft. Das ist normalerweise gut, aber wenn das Spiel schnell gestartet und gestoppt wird, wird ein Rahmen angefordert, ohne eine Möglichkeit, es abzubrechen. Also, was wir brauchen, ist eine Möglichkeit, Frames abzubrechen. Zum Glück gibt es eine Funktion dafür: cancelAnimationFrame (). Das Anfordern eines Rahmens gibt tatsächlich eine Frame-ID zurück, die wir an die Cancelling-Funktion übergeben können: Achten Sie darauf, dies in der FPS-Throttling-Bedingung zu tun, auch wenn Sie es gehalten haben. Nun können Sie stop () implementieren: Zusätzlich zu dieser Implementierung sollten auch Event-Handling und andere Hintergrundaufgaben (wie die, die über setInterval () oder Web-Worker auftreten, pausiert werden, wenn die Main-Schleife pausiert wird. Dies ist in der Regel nicht eine große Sache, denn sie können nur die laufende Variable zu sehen, ob sie ausführen oder nicht. Beachten Sie außerdem, dass ein Pausieren in Multiplayer-Spielen dazu führen wird, dass der Spieler-Client nicht mehr synchronisiert wird, so dass das Spiel generell das Spiel verlassen oder den Player wieder in seine aktualisierte Position bringen soll, wenn die Hauptschleife erneut gestartet wird (nach Bestätigung mit dem Spieler, den sie wirklich wollen) Pause). Das Starten der Schleife ist schwieriger. Wir müssen auf vier Dinge achten. Zuerst sollten wir nicht erlauben, die Hauptschleife zu beginnen, wenn ihr bereits begonnen hat, da das mehrfache Rahmen auf einmal verlangt und uns verlangsamt. Zweitens müssen wir sicherstellen, dass das Umschalten zwischen dem Starten und Stoppen schnell nicht Probleme verursacht. Drittens müssen wir den Anfangszustand des Spiels machen, bevor irgendwelche Updates auftreten, da unsere Hauptschleife nach dem Update zeichnet. Schließlich müssen wir einige Variablen zurücksetzen, um zu vermeiden, dass die Zeit simuliert wird, die verstrichen ist, während das Spiel pausiert wurde. Darüber hinaus sollten Ereignishandler und Hintergrund-Tasks wieder aufnehmen, sobald das Spiel erneut gestartet wird. Hier gehen wir: Node. jsIO. js und IE9 Unterstützung Das Hauptproblem mit unserem Code im Moment, die zurück Unterstützung für node. jsIO. js hält, sowie IE9 und früher, wenn Sie über diese Browser kümmern, ist der Mangel an requestAnimationFrame () Und cancelAnimationFrame (). Wir können es mit Polyfills nach Timern ausgleichen: Weve hat das Kompatibilitätsproblem zur Unterstützung von Date. now () reduziert, was im IE8 nicht verfügbar ist. Wenn Sie wirklich brauchen IE8-Unterstützung, können Sie neue Datum () anstatt, aber youll erzeugen eine Menge neuer Objekte und das wird eine Menge von Garbage Collection, die Ihr Spiel stottern wird zu schaffen. Und IE8 ist langsam genug, um damit beginnen, dass es kaum Sinn macht, etwas JavaScript-intensive auf sie zu tun. Wrapping Das war viel zu denken. Wenn Sie Ihre Main-Loop die einfache Möglichkeit, können Sie einfach meine MainLoop. js Open-Source-Projekt. Dann müssen Sie nicht über all diese Probleme zu kümmern. Wenn youre Ihr eigenes Rollen, gibt es einige allgemeine Reinigung, die getan werden könnte. Zum Beispiel sollte die Box in einer eigenen Klasse verpackt werden. Das gesamte Skript sollte in einem IIFE mit einer exportierten Schnittstelle verpackt werden, um zu verhindern, dass der globale Namensraum in Browsern verschmutzt oder als CommonJS - oder AMD-Modul verpackt wird. MainLoop. js tut dies (und mehr) für Sie, aber im großen und ganzen haben wir ziemlich gut gemacht. Schließlich möchte ich mich bei Glenn Fiedler für das Schreiben der klassischen Fix your timestep bedanken, die den Ausgangspunkt für eine Menge der Arbeit hier war. Dank Ian Langworth sowie für die Überprüfung einer kürzeren Version dieses Artikels, die ich in meinem Buch über die 3D-Browsergames und für einige Tipps über Web-Arbeitnehmer aufgenommen. Wenn nach all dem, youre immer noch auf der Suche nach mehr Ressourcen auf das Thema, könnten Sie auch prüfen, aus dem Spiel Programming Patterns Bücher nehmen oder die weniger gründliche nehmen bei MDN. Fünf-Jahres-Durchschnitt Globale Temperatur-Anomalien von 1881 bis 2006 Visualization Credits Alex Kekesi (GST): Lead Animator Lori Perkins (NASAGSFC): Animator James Hansen Ph. D. (NASAGSFC GISS): Wissenschaftler Makiko Sato Ph. D. (NASAGSFC GISS): Wissenschaftler Reto A. Ruedy Ph. D. (NASAGSFC GISS): Wissenschaftler Ken Lo Ph. D. (NASAGSFC GISS): Wissenschaftler David Lea Ph. D. (Universität von Kalifornien, Santa Barbara): Wissenschaftler Martin Medina-Elizade (Universität von Kalifornien, Santa Barbara): Wissenschaftler NASAGoddard Space Flight Center Wissenschaftliche Visualisierung Studio Daten zur Verfügung gestellt von Robert B. Schmunk (NASAGSFC GISS) Kurz-URL, zum Teilen dieser Seite: svs. gsfc. nasa. gov3375 GCMD Schlüsselwörter können im Internet mit dem folgenden Zitat gefunden werden: Olsen, LMG Major, K. Schin, J. Scialdone, S. Ritz, T. Stevens, M. Morahan, A. Aleman, R. Vogel, S. Leicester, H. Weir, M. Meaux, S. Grebas, C. Solomon, M. Holland, T. Northcutt, RA Restrepo, R. Bilodeau, 2013. NASAGlobal Change Master Verzeichnis (GCMD) Earth Science Keywords. Version 8.0.0.0.0 Orte, die Sie vielleicht gesehen haben: die Associated Press, ABC, Albuquerque Tribune, BBC, CBC, CBS, Cleveland Plain Händler, CTV, Detroit Free Press, Discovery Channel, Fox News, Houston Chronicle, Indianapolis Star, KIRO-TV (Kansas City), KUTV-TV (Salt Lake City), MSNBC, Neuer Wissenschaftler, Newsday, Die New York Times, Salon, San Francisco Chronik, San Jose Mercury Nachrichten, Toronto Star, Das Wall Street Journal, die Washington Post, WNBC-TV (New York), WPXI-TV (Pittsburgh) und WSMV-TV (Nashville). International coverage: Australia, Canada, China, Cuba, Denmark, France, Germany, India, Ireland, Japan, Norway, Philippines, Qatar, Russia, South Africa, Spain, Turkey, United Arab Emirates, United Kingdom. Browse Stories

Comments

Popular posts from this blog

Stockmann Tapiola Forex Kaufen

Option Handel Leerverkäufe

Types Of Binary Optionen