通过查找平均FPS来提高画布游戏性能

时间:2016-12-13 21:04:28

标签: javascript html5 performance canvas

看一下我游戏的运动功能:

https://jsfiddle.net/qk7ayx7n/92/

var canvas = document.getElementById("canvas");
var ctx=canvas.getContext("2d");
height = window.innerHeight;
canvas.width = window.innerWidth; 
canvas.height = height; 

playerY = height / 2;
playerX = 50;
var circle = new Image();
circle.src = "https://s21.postimg.org/4zigxdh7r/circ.png";

ctx.drawImage(circle, playerX, playerY);

move();

function move(){

velocity = height * 0.00050; // the velocity should be proptional to screen height.
startPos = playerY,
endPos = 0,
distanceY = endPos - playerY,  
startTime = Date.now(),
duration = Math.abs(distanceY) / velocity;
requestAnimationFrame(startMoving);

function startMoving(){
    var elapsedTime = Math.min(Date.now() - startTime, duration),
    cbEnd = false;
    if (elapsedTime < duration){ //time's up
        setTimeout(function() {
        requestAnimationFrame(startMoving);
        }, 1000 / 60);
    }
    else cbEnd = true;
    playerY = startPos - (elapsedTime * velocity);
    console.log(playerY);
    ctx.clearRect(0, 0, window.innerWidth, height);
    ctx.drawImage(circle, playerX, playerY); //drawing circle
    if(cbEnd) console.log("over");
    }
}

现在,我将解释:我的实际游戏是一个游戏,随着游戏的进行,玩家的速度会发生变化。速度与窗户的高度成正比,因为玩家的目标是向上移动。 我使用this technique来更好地控制我执行的玩家数量。我们稍后会解决这个问题。

我还使用this technique(参见答案)测量时间,以防最后一帧出现滞后,它只会覆盖它应该覆盖的距离,这也意味着在所有设备上始终按时到达目标Y.

FPS平均值是我遇到的最大问题。不同的设备有不同的规格。为了为所有设备创造一个好游戏,我必须掌握这个功能:

setTimeout(function() {
var fps = 60;
requestAnimationFrame(startMoving);

}, 1000 / fps);

我已经在许多设备上测试了我的游戏,有些fps需要为40,50,30或其他东西,以便游戏顺利运行(这意味着每个玩家&#34;移动&#34;将会是等于它以前,否则他们将经历滞后)。所以我在想,要么像游戏一样秘密地运行游戏,要么加载#34;这是第一次找出平均FPS,或保持某种学习曲线,以调整此功能运行的次数。 无论哪种方式,我都不知道如何完美地实现它,我知道它可能很难,但我需要一些帮助。

2 个答案:

答案 0 :(得分:0)

canvas.getContext("2d") - 很慢。

您需要使用 webgl 。 要使用webgl,请使用 Pixi.js 。这是一个非常好的图书馆。

在此DEMOwithout source

处拍摄

答案 1 :(得分:0)

帧率

要使用requestAnimationFrame(rAF)控制帧速率,您需要监视每次调用rAF回调的时间。这可以通过使用传递给你的函数的第一个参数来完成。

示例获取60帧的平均帧速率。

&#13;
&#13;
function log(data){
    var div = document.createElement("div");
    div.textContent = data;
    document.body.appendChild(div);
    scroll(0,10000);
}
var samples = [];
function myLoop(time){
    if(samples.length < 60){
        samples.push(time);
        requestAnimationFrame(myLoop) 
    }else{
        log("First 60 callback times in ms.");
        samples.forEach(s=>log(s.toFixed(3)));
        log("Mean frame time : "+ ((samples[59]-samples[0])/60).toFixed(3))
        log("Mean frame rate : "+ (1000/((samples[59]-samples[0])/60)).toFixed(0))
    }
}
requestAnimationFrame(myLoop) 
&#13;
&#13;
&#13;

此示例等待4秒(大约)采样帧速率。

&#13;
&#13;
function log(data){
    var div = document.createElement("div");
    div.textContent = data;
    document.body.appendChild(div);
    scroll(0,10000);
}
log("4 second wait for stable");
var waitFor = 240; // wait for browser to be nice.
var samples = [];
function myLoop(time){
    if(waitFor > 0){
        waitFor -= 1;
        requestAnimationFrame(myLoop) 
        return;
    }
    if(samples.length < 60){
        samples.push(time);
        requestAnimationFrame(myLoop) 
    }else{
        log("First 60 callback times in ms.");
        samples.forEach(s=>log(s.toFixed(3)));
        log("Mean frame time : "+ ((samples[59]-samples[0])/60).toFixed(3))
        log("Mean frame rate : "+ (1000/((samples[59]-samples[0])/60)).toFixed(0))
    }
}
requestAnimationFrame(myLoop) 
&#13;
&#13;
&#13;

要控制帧速率,你需要忽略早期帧,如果它们进来的话。有一点点克服,因为帧时间不完美,但是因为你知道帧不会比1/60快,所以很容易处理用。

&#13;
&#13;
const FRAME_RATE = 30;
// set min frame time at frame rate sub 1/4 frame
const FRAME_MIN_TIME = (1000/FRAME_RATE) - (1000/(60*4));
var lastFrameTime = 0;    

function log(data){
    var div = document.createElement("div");
    div.textContent = data;
    document.body.appendChild(div);
    scroll(0,10000);
}
var samples = [];
function myLoop(time){
    // if the frame is early call the next frame and dont render
    if(time - lastFrameTime < FRAME_MIN_TIME){            
        requestAnimationFrame(myLoop);
        return;
    }
    lastFrameTime = time;

    if(samples.length < 60){
        samples.push(time);
        requestAnimationFrame(myLoop) 
    }else{
        log("First 60 callback times in ms.");
        samples.forEach(s=>log(s.toFixed(3)));
        log("Mean frame time : "+ ((samples[59]-samples[0])/60).toFixed(3))
        log("Mean frame rate : "+ (1000/((samples[59]-samples[0])/60)).toFixed(0))
    }
}
requestAnimationFrame(myLoop) 
&#13;
&#13;
&#13;

好数字?

使用javascript很难获得良好的帧速率估计,尤其是在启动时,因为有很多事情会导致帧丢失。根据页面上发生的情况,您可能需要几秒钟或更长时间才能可靠地估算游戏负载。

处理帧速率的最佳方法是首先允许一些稳定时间。监视帧速率,当您看到连续多帧丢失时,请等待。获得一致的费率后,使用最小费率作为基本费率,如第二个片段所示,限制框架呈现。

您只能在rate = 60/n处获得一致的帧速率,其中n是整数&gt; = 1.帧速率60,30,20,15,12,10,8.87 ......依此类推。