看一下我游戏的移动功能:
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 或其他值才能使游戏顺利运行(这意味着每个玩家的“移动”将等于之前的移动,否则他们会遇到滞后)。所以我在想,要么在游戏第一次“加载”时 secret 运行游戏并找出平均 FPS,要么保持某种学习曲线以调整该函数运行的次数。 不管怎样,我真的不知道如何完美地实现它,我知道这可能很难,但请我需要一些帮助。
最佳答案
帧速率
要使用 requestAnimationFrame (rAF) 控制帧速率,您需要监视每次调用 rAF 回调的时间。这可以通过使用 rAF 传递给函数的第一个参数来完成。
示例获取 60 帧的平均帧速率。
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)
此示例在采样帧速率之前等待 4 秒(大约)。
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)
要控制帧速率,您需要忽略早期帧(如果它们进入)。由于帧时间并不完美,所以有一点困惑,但因为您知道帧不会比 1/60 快,所以很容易处理与。
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)
数字不错吗?
使用 javascript 很难获得良好的帧速率估计,尤其是在启动时,因为有很多事情可能会导致丢帧。根据页面上发生的情况,您可能需要几秒钟或更长时间才能可靠地估计游戏的负载。
处理帧速率的最佳方法是首先留出一些稳定时间。监视帧速率,当您看到连续许多帧丢失时,请等待。一旦获得一致的速率,请使用最小速率作为基本速率,限制帧渲染,如第二个片段所示。
您只能在 rate = 60/n
下获得一致的帧速率,其中 n 是 >= 1 的整数。帧速率 60、30、20、15、12、10、8.87...等等。
关于javascript - 通过查找平均 FPS 提高 Canvas 游戏性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41130520/