2013-09-25 10 views
9

Ich beginne die SchleifeJavascript - Kann nicht Framerate einstellen - request

function gameLoop(){ 
    update(); 
    draw(); 
    requestAnimFrame(gameLoop); 
} 

var requestAnimFrame = window.requestAnimationFrame || 
        window.webkitRequestAnimationFrame || 
        window.mozRequestAnimationFrame || 
        window.oRequestAnimationFrame || 
        window.msRequestAnimationFrame || 
        function(callback) { 
         window.setTimeout(callback, 1000/1); 
        }; 
  1. ich die Framerate nicht einstellen. Es ist immer sehr schnell. Warum kann ich es nicht auf 1 Bild pro Sekunde ändern? Ich möchte das nur zu Testzwecken tun.
  2. Muss ich die Leinwand jedes Mal löschen? Es scheint gut zu funktionieren, ohne es zu klären.

Danke. Hier

ist ein Link zu einer Geige für den kompletten Code: complete code

Dank

Antwort

9

rAF gesperrt ist die Synchronisation zu überwachen, typischerweise 60 Hz, so dass wir nicht die FPS für sie an sich anpassen (Der Browser kann FPS reduzieren, wenn die Registerkarte inaktiv ist oder an Batterien angeschlossen ist).

Auch das, was Sie versuchen zu ändern, ist die Fallback für die Poly-Fill; Das heißt: Wenn rAF im Browser nicht unterstützt wird, wird stattdessen setTimeout verwendet. Die meisten Browser heutzutage tun Unterstützung rAF (auch nicht vorfixiert), so dass die setTimeout wird nie verwendet werden.

können Sie zwei Dinge tun:

  • rAF in der Schleife Ersetzen durch setTimeout direkt mit (bei der Prüfung)

Beispiel:

var FPS = 1; 

function testLoop() { 

    ... ordinary code 

    setTimeout(testLoop, 1000/FPS); 
} 
  • Drosselklappen rAF durch die Verwendung ein Zähler:

Beispiel:

var framesToSkip = 60, 
    counter = 0; 

function loop() { 

    if (counter < framesToSkip) { 
     counter++; 
     requestAnimationFrame(loop); 
     return; 
    } 

    /// do regular stuff 

    counter = 0; 
    requestAnimationFrame(loop); 
} 

MODIFIED FIDDLE HERE

Es gibt wahrscheinlich bessere Möglichkeiten Drosselung zu implementieren, aber ich versuche zu zeigen, nur das Grundprinzip. Dies wird immer noch mit voller Geschwindigkeit laufen, 60 FPS, aber Ihr Code wird nur minimale Operationen ausführen und nur wenn der Zähler seine Anzahl erreicht hat, wird er den Hauptcode ausführen.

Sie müssen die Zeichenfläche nicht jedes Mal löschen, wenn das, was Sie als Nächstes zeichnen, zuvor gezeichneten Inhalt enthält oder wenn Sie es natürlich beibehalten möchten. Sie können einen Teil auch löschen, um ihn bei Bedarf weiter zu optimieren.

0

requestAnimationFrame wird mit der maximal erreichbaren Bildrate laufen (bis zu 60 fps). Dies liegt daran, dass Sie immer den nächsten Animationsrahmen erhalten.

Der Parameter, den Sie angepasst haben, ist nur für den Polyfill, der aktiv ist, wenn Ihr Browser keine Implementierung von requestAnimationFrame hat.

Wenn Sie versuchen möchten, eine Sekunde lang zu Testzwecken zu malen, versuchen Sie stattdessen setInterval.

0

So funktioniert requestAnimationFrame funktioniert. Wenn Sie eine bestimmte Bildrate wünschen, verwenden Sie nur setTimeout.

Normalerweise würden Sie einen Parameter nehmen, der die aktuelle Zeit ist. Vergleichen Sie es mit der Zeit des letzten Frames, um herauszufinden, wie weit sich die Animation bewegen sollte.

1

Die Art und Weise, wie Browser und JavaScript funktionieren, erschwert die Einrichtung einer festen Bildfrequenz. Nehmen wir an, du möchtest jede Sekunde etwas machen, wie zum Beispiel das Aktualisieren und Zeichnen. Eine Möglichkeit wäre, window.setTimeout() mit einer Einstellung von einer Sekunde aufzurufen. Aber das Problem ist, dass dies nicht so zuverlässig ist, selbst wenn Sie jede Sekunde einen Callback konfigurieren, können Sie nicht sicher sein, dass alle Callbacks rechtzeitig sind. Eine hohe Prozessorlast beispielsweise könnte dazu führen, dass die Rückrufe viel später ankommen, als sie sollten. Und selbst wenn die Callbacks pünktlich sind, haben Sie keine Kontrolle darüber, wann die eigentliche Zeichnung auf den Bildschirm kommt.

Ein besserer Weg, um es zu handhaben ist, die Tatsache zu akzeptieren, dass Sie nicht ein sehr genaues Timing Ihrer Anrufe erhalten können, und stattdessen, wenn Sie einen Anruf erhalten, berechnen Sie, wie viel Zeit vergangen ist und danach handeln . Das bedeutet, dass Sie das System die Bildrate bestimmen lassen und dass Sie nur Ihre Animation oder Ihr Spiel aktualisieren müssen, je nachdem wie viel Zeit vergangen ist.

requestAnimationFrame ist eine neuere Funktionalität, die von den meisten Browsern inzwischen unterstützt wird und besonders nützlich für Spiele ist. Es wird jedes Mal aufgerufen, wenn der Browser zum Zeichnen bereit ist, was gut ist. Dann werden Sie wissen, dass die Aktualisierungen und die Zeichnung, die Sie gerade ausführen, kurz vor dem eigentlichen Bild auf dem Bildschirm angezeigt werden.

Hier ist ein Beispiel, wie Sie Ihren GameLoop aktualisieren können, um den Zeitunterschied zu berücksichtigen.

6

Ein bisschen spät auf die Party, aber hier ist, wie Sie den Vorteil von RAF bekommen, während auch Frames/Sekunde steuern.

Hinweis: requestAnimationFrame hat jetzt einen besseren Weg, Dinge zu tun als mit dem Code-Muster in meiner ursprünglichen 3 Jahre alten ursprünglichen Antwort ... siehe mein Update unten für den neuen und verbesserten Weg.

[Update: request hat nun eine bessere Möglichkeit der Drosselung]

Die neue Version von requestAnimationFrame jetzt automatisch in einem aktuellen Zeitstempel sendet, dass Sie Ihre Codeausführung drosseln können.

Hier Codebeispiel Code alle 1000 ms auszuführen:

var nextTime=0; 
var delay=1000; 

function gameLoop(currentTime){ 
    if(currentTime<nextTime){requestAnimationFrame(gameLoop); return;} 
    nextTime=currentTime+delay; 
    // do stuff every 1000ms 
    requestAnimationFrame(looper); 
} 

}

+0

Klingt sehr logisch und clever. – nerkn

+0

sollten Sie nicht irgendwie setTimeout und requestAnimationFrame tauschen? In Ihrem Beispiel werden update und draw beim setTimeout-Ereignis aufgerufen, immer noch asynchron, während der gameloop() -Body synchron ist (aber nichts tut, als das Zeitlimit zu setzen) –

+0

@DanielAlder. Dieser Code ist ein paar Jahre alt und jetzt sendet 'requestAnimationFrame' automatisch einen Zeitstempel, so dass 'setTimeout' nicht mehr benötigt wird. Verwenden Sie den Zeitstempel, um die Animation zu drosseln. – markE

2

Sie sollten Blick auf diese steuern müssen Artikel, der eine angemessene Behandlung des Themas gibt. http://creativejs.com/resources/requestanimationframe/

var fps = 15; 
function draw() { 
    setTimeout(function() { 
     requestAnimFrame(draw); 
     // Drawing code goes here 
    }, 1000/fps); 
} 

Hier ist der Code, den ich glaube, Sie wollen, aber in dem Original-Artikel sagte, es verwendet request, aber hier ist requestAnimFrame verwendet. Ich denke, vielleicht hat sich das geändert und du solltest jetzt requestAnimFrame verwenden.requestAnimationFrame funktionierte nicht für mich, während requestAnimFrame das tat.

Verwandte Themen