Kód od @Slaks vám poskytuje pouze okamžité FPS posledního snímku, který se může lišit nebo být zavádějící s škytavkou. Dávám přednost použití snadno zapisovatelného a vypočítatelného filtru dolní propusti k odstranění rychlých přechodových jevů a zobrazení rozumného pseudoprůměru nedávných výsledků:
// 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);
„Poločas rozpadu“ tohoto filtru – počet snímků potřebný k přesunu ze staré hodnoty na novou stabilní hodnotu – je filterStrength*Math.log(2)
(zhruba 70 % síly).
Například síla 20
se přesune do poloviny k okamžité změně ve 14 snímcích, 3/4 cesty tam za 28 snímků, 90 % cesty tam za 46 snímků a 99 % cesty tam za 92 snímků. U systému běžícího rychlostí přibližně 30 snímků za sekundu bude náhlý, drastický posun ve výkonu zřejmý během půl sekundy, ale stále „zahodí“ anomálie jednoho snímku, protože posunou hodnotu pouze o 5 % rozdílu.
Zde je vizuální srovnání různých sil filtrů pro hru ~30 snímků za sekundu, která má chvilkový pokles na 10 snímků za sekundu a později až na 50 snímků za sekundu. Jak vidíte, nižší hodnoty filtru rychleji odrážejí „dobré“ změny, ale jsou také náchylnější k dočasným škytavkám:
Nakonec je zde příklad použití výše uvedeného kódu ke skutečnému testování „herní“ smyčky.
V gameLoop
, podívejte se na rozdíl mezi new Date
a new Date
z poslední smyčky (uložte ji do proměnné).
Jinými slovy:
var lastLoop = new Date();
function gameLoop() {
var thisLoop = new Date();
var fps = 1000 / (thisLoop - lastLoop);
lastLoop = thisLoop;
...
}
thisLoop - lastLoop
je počet milisekund, které uplynuly mezi dvěma smyčkami.
Toto používám k výpočtu 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');
}
}