2011-10-06 16 views
9

Come risolvere diversi FPS in requestAnimationFrame su diversi browser?
Sto creando un gioco 3D utilizzando THREE.js che utilizza requestAnimationFrame ed è veloce su Google Chrome 15.
Tuttavia, è veramente lento su Firefox 6 e veramente molto lento (più lento di Firefox) su IE9.
Questo è davvero un problema grande e mi chiedo se c'è una soluzione a questo.Come risolvere diversi FPS in requestAnimationFrame su diversi browser?

Grazie.

+1

Il modo per risolverlo è fare in modo che tutto il codice che stai eseguendo dalla richiamata funzioni velocemente. Come farlo è impossibile da dire senza vedere il codice ... –

risposta

5

Per quanto ne so, non c'è modo di risolvere questo problema, oltre a rendere il tuo codice meno dispendioso in termini di risorse.

Chrome sembra essere il browser più veloce, ma in genere FF non è molto indietro, ma IE è ancora lento. A seconda dei metodi di rendering, canvas, svg o webGL, è anche molto dipendente dall'hardware locale in quanto utilizza il clientide per la maggior parte delle cose e complicati rendering di WebGL richiedono una potente GPU per ottenere una buona framerate.

Ci sono modi per misurare il framerate al volo e modificare le animazioni di conseguenza.
Ecco un esempio molto semplice che misura il framerate.

function step(timestamp) { 
 
    var time2 = new Date; 
 
    var fps = 1000/(time2 - time); 
 
    time = time2; 
 
\t 
 
    document.getElementById('test').innerHTML = fps; 
 
    window.requestAnimationFrame(step); 
 
} 
 

 
var time = new Date(), i = 0; 
 
window.requestAnimationFrame(step);
<div id="test"></div>

Questa è solo una misura istantanea che non è così preciso, che vorreste probabilmente qualcosa che misura nel corso del tempo per ottenere una più corretta framerate per il browser in uso.

noti inoltre l'argomento timestamp, che in requestAnimationFrame è timestamp ad alta risoluzione con un minimo di precisione 1 millisecondi, che può anche essere utilizzato per deterine la velocità dell'animazione e ogni ritardo browser.

+2

IE9 + è in realtà piuttosto veloce. A volte più veloce di FF, nella mia esperienza. – kangax

14

La cosa comune da fare è creare una variabile deltaTime (dt) che sia poi utilizzata come parametro per ogni ciclo di animazione/aggiornamento.

Il codice serve solo per visualizzare il problema/soluzione.

// ... 
timer: function(){ 
    var now = new Date().getTime(); // get current time 
    this.controls.dt = now - this.controls.time; // calculate time since last call 
    this.controls.time = now; // update the current application time 
    this.controls.frame++; // also we have a new frame 
    return this.controls.dt ; 
} 

per qualsiasi chiamata alla funzione di rendering poi passare dt

// we call the update function with every request frame 
update: function(){ 
    var dt = this.timer(); 
    _.each(this.activeViews, function(item){ item.update(dt); }); // this is underscore.js syntax 
} 

item.update (dt) sembra che

//... 
var x = this.position.get(x); 
x = x + (10*dt); // meaning: x increases 10 units every ms. 
this.position.x = x; 
2

Su alcuni browser requestAnimationFrame funziona qualcosa come

setTimeout(callback, 1000/(16 + N)

dove N è il tempo richiesto per l'esecuzione del codice. Il che significa che blocca il tuo FPS a 62Hz, ma se il tuo codice funziona lentamente, si limiterà a qualcosa di più basso. Praticamente cerca di fare un gap di 16ms tra ogni gap. Naturalmente, questo non è vero per tutti i browser e probabilmente cambierà comunque in futuro, ma potrebbe comunque darti un'idea di come funziona.

Anche se è stato implementato lo stesso in tutti i browser, ci sono molti fattori che influenzano le prestazioni del vostro codice, ecc Non si può mai essere sicuri che il codice verrà eseguito ad una frequenza costante.

3

Il framework Crafty fa qualcosa che è un po 'diverso, ma potrebbe funzionare in alcuni casi: il numero di tick di gioco per estrazione non è costante. Piuttosto, nota quando il framerate sta cadendo dietro a qualche bersaglio ideale, e passerà in rassegna più battute prima di eseguire la sottofase di acquisizione. Puoi vedere lo step function su github.

Questo metodo funziona bene fino a quando il gioco sarebbe senza intoppi. Ma se provi qualcosa di più intensivo del processore, può tendere a esacerbare la situazione, dato che darà priorità alla logica del gioco rispetto all'animazione.

In ogni caso, funzionerà solo se la logica del gioco e rendere la logica sono un po 'disaccoppiati. (Se fossero completamente disaccoppiati potresti essere in grado di metterli in loop completamente separati.)

Problemi correlati