2011-01-24 1 views

risposta

24

In gameLoop, guarda la differenza tra new Date e new Date dall'ultimo ciclo (memorizzarlo in una variabile).
In altre parole:

var lastLoop = new Date; 
function gameLoop() { 
    var thisLoop = new Date; 
    var fps = 1000/(thisLoop - lastLoop); 
    lastLoop = thisLoop; 
    ... 
} 

thisLoop - lastLoop è il numero di millisecondi che passano tra i due anelli.

+0

sto ottenendo fps: -1295907214150 sto usando fps come globale Edit: si fa la stessa cosa come un var locale -12 e roba – CyanPrime

+0

@Cyan: Ho dimenticato di aggiungere parentesi; scusa. Dovrebbe funzionare ora. – SLaks

+0

Ha funzionato, grazie mille. – CyanPrime

83

Il codice di @Slaks fornisce solo l'FPS istantaneo dell'ultimo frame, che può variare o essere fuorviante con singhiozzo. Preferisco usare un filtro passa-basso di facile write-and-elaborazione per rimuovere transienti veloci e visualizzare una pseudo-media ragionevole di risultati recenti:

// The higher this value, the less the fps will reflect temporary variations 
// A value of 1 will only keep the last value 
var filterStrength = 20; 
var frameTime = 0, lastLoop = new Date, thisLoop; 

function gameLoop(){ 
    // ... 
    var thisFrameTime = (thisLoop=new Date) - lastLoop; 
    frameTime+= (thisFrameTime - frameTime)/filterStrength; 
    lastLoop = thisLoop; 
} 

// Report the fps only every second, to only lightly affect measurements 
var fpsOut = document.getElementById('fps'); 
setInterval(function(){ 
    fpsOut.innerHTML = (1000/frameTime).toFixed(1) + " fps"; 
},1000); 

Il 'emivita' di questo filtro il numero dei fotogrammi necessari per spostarsi a metà strada dal vecchio valore in un nuovo valore stabile: è filterStrength*Math.log(2) (circa il 70% della forza).

Ad esempio, un punto di forza di 20 si sposterà a metà strada ad una variazione istantanea 14 fotogrammi, 3/4 del tragitto in 28 fotogrammi, il 90% del tragitto in 46 cornici, e il 99% del tragitto in 92 frame. Per un sistema che gira a circa 30fps, un improvviso, drastico cambiamento nelle prestazioni sarà ovvio in mezzo secondo, ma continuerà a "buttare via" le anomalie a frame singolo in quanto modificheranno il valore solo del 5% della differenza.

Ecco un confronto visivo di diverse intensità del filtro per un gioco a ~ 30 fps che ha un calo momentaneo a 10 fps e successivamente aumenta la velocità a 50 fps. Come si può vedere, i valori del filtro inferiori riflettono in modo più rapido 'buoni' i cambiamenti, ma sono anche più sensibili a singhiozzo temporanei:
enter image description here

Infine, ecco an example di utilizzare il codice per realtà di riferimento un ciclo 'gioco' di cui sopra .

+0

Grafica molto bella! Come hai fatto? –

+3

@BennyNeugebauer Quanto sopra è stato creato in Excel, solo perché è stato leggermente più facile per una tantum di [utilizzando HTML5 Canvas per una grafica abbastanza IIR] (http://phrogz.net/js/framerate-independent-low-pass- filter.html). – Phrogz

+0

C'è qualche ragione per cui ottengo fps infiniti quando si utilizza il frame di animazione della richiesta. Sto usando una forza filtro di 1 per l'FPS più accurato? accade di tanto in tanto (Fps infiniti): http: // jsfiddle.net/CezarisLT/JDdjp/10/ – Kivylius

2

Io lo uso per il calcolo fps

var GameCanvas = document.getElementById("gameCanvas"); 
    var GameContext = doContext(GameCanvas,"GameCanvas"); 
    var FPS = 0; 
    var TimeNow; 
    var TimeTaken; 
    var ASecond = 1000; 
    var FPSLimit = 25; 
    var StartTime = Date.now(); 
    var TimeBefore = StartTime; 
    var FrameTime = ASecond/FPSLimit; 
    var State = { Title:0, Started:1, Paused:2, Over:3 }; 
    var GameState = State.Title; 

    function gameLoop() { 
    requestAnimationFrame(gameLoop); 
    TimeNow = Date.now(); 
    TimeTaken = TimeNow - TimeBefore; 

    if (TimeTaken >= FrameTime) { 
     FPS++ 
     if((TimeNow - StartTime) >= ASecond){ 
     StartTime += ASecond; 
     doFPS(); 
     FPS = 0; 
     } 

     switch(GameState){ 
     case State.Title : 
      break; 
     case State.Started : 
      break; 
     case State.Paused : 
      break; 
     case State.Over : 
      break; 
     } 
     TimeBefore = TimeNow - (TimeTaken % FrameTime); 
    } 
    } 

    Sprites.onload = function(){ 
    requestAnimationFrame(gameLoop); 
    } 

    function drawText(Context,_Color, _X, _Y, _Text, _Size){ 
    Context.font = "italic "+ _Size +" bold"; 
    Context.fillStyle = _Color; 
    Context.fillText(_Text, _X, _Y); 
    } 

    function doFPS()(
    drawText(GameContext,"black",10,24,"FPS : " + FPS,"24px"); 
    } 

    function doContext(Canvas,Name){ 
    if (Canvas.getContext) { 
     var Context = Canvas.getContext('2d'); 
     return Context; 
    }else{ 
     alert(Name + ' not supported your Browser needs updating'); 
    } 
    } 
1

Che dire requestAnimationFrame?

var before,now,fps; 
before=Date.now(); 
fps=0; 
requestAnimationFrame(
    function loop(){ 
     now=Date.now(); 
     fps=Math.round(1000/(now-before)); 
     before=now; 
     requestAnimationFrame(loop); 
     console.log("fps",fps) 
    } 
);