本文分析了fish ie tank的算法。
主要在fpsometer.js中。
FpsMeter.prototype.Draw = function (score, snap) {
var now = new Date();
/* Calculate time delta since last time this method was called ---------*/
this.timeDeltaSinceLastFrame = .001;
if (this.lastFrameTime != 0) //如果这不是第一次执行的话,用timeDeltaSinceLastFrame去保存距离上次测试函数被调用的时间。
this.timeDeltaSinceLastFrame = now - this.lastFrameTime;
//timeDeltas用来控制鱼的游速,比如/1000000的话,鱼基本是不动的。
this.timeDeltaS = this.timeDeltaSinceLastFrame / 1000;
//记录不是第一次进入本函数,并保存时间.
this.lastFrameTime = now;
/* Calculate frame rate, since last time this method was called ---------*/
//使用fpsDisplayUpdateFrequency来控制,fps数值在网页上面刷新的时间。如果没有到达刷新的时间,虽然结果还是在一直计算,但是在屏幕上面不会更新。
if (now - this.currentSecond < this.fpsDisplayUpdateFrequency) {
this.framesThisPeriod++; //在规定的时间内,记录进行draw的次数。
}
else {
this.currentSecond = now;//首先更新当前的时间
//fps 应该是每秒的的传输贞数
this.fps = this.framesThisPeriod / (this.fpsDisplayUpdateFrequency / 1000);
this.framesThisPeriod = 1;//因为这次没有进入if(right)的判断,所以在此处将运算次数记为1.
var timingDelayReached = ((now.getTime() - this.timeFpsDisplayLastChanged) > this.fpsDisplayUpdateFrequency);//这个变量是bool型的,用来判断距上次显示的时间是不是到了应该改变的时间。到了是true,否则false
var fpsNotChangedYet = (this.timeFpsDisplayLastChanged == 0); //因为timeFpsDisplayLastChanged初值为0,所以用来判断是不是第一次改变fps的值在屏幕上。
//如果到了需要改变fps的数值,或者第一次进入该函数的时候,则回去改变屏幕上面fps的数值。
if (timingDelayReached || fpsNotChangedYet) {
this.timeFpsDisplayLastChanged = now.getTime(); //记录fps数值改变的时间
this.displayedFps = Math.round(this.fps > this.targetFPS ? this.targetFPS : this.fps);
//math.round()方法的作用是把当前数字舍入为最接近的一个数值。我们在初始化的时候,会规定一个fps显示的最大值。如果大于这个最大值的话,则返回最大值。
}
}
//如果当前的时间-网页打开初始化的时间 < 2s的话,计算fps的数值. 但是这个数据不会显示在屏幕上,而是在后台计算.在屏幕上面显示的一直是calculating
if ((now - this.fpsResetTime < 2000)) {
this.frames++;
// calculate frames live
this.fps = Math.min(this.frames / ((now - this.fpsResetTime) / 1000), this.targetFPS);
//计算原理同上面的计算一致.
this.displayedFps = "calculating";
}
// calculate fps
//第一次的值为-60,第二次为1.显示的值为经过计算的百分比*最大值.百分比在函数的最后进行计算.
var displayedFps = Math.round((this.meterPercent * this.targetFPS));
this.meterFps = displayedFps;
// -- add by chao
var TimesNotChangedYet = (this.timechanged == 0);
var timingDelayChanged = ((now.getTime() - this.timechanged) > 1000);
if (timingDelayChanged || TimesNotChangedYet)
{
console.log("displayedFps = " + displayedFps);
this.timechanged = now.getTime();
}
// add by chao --
// calculate meter:
if (this.fps > 1) {
this.meterPercentGoal = (this.fps > this.targetFPS ? this.targetFPS : this.fps) / this.targetFPS; //a maximum of targeFPS fps are drawn so cap the gauge at targetFPS.
//meterPercentGoal是当前fps/最大fps,为当前的百分比.
if (this.meterPercent == -1) {
this.meterPercent = .01;
//所有的值都是从1开始计算的.
}
var delta = Math.abs(this.meterPercent - this.meterPercentGoal);
//delta为上次与这一次的百分比的差.
if (this.meterPercent < this.meterPercentGoal) {
//snap 在这个算法里面没有被定义,所以这个判断一定会进.
if (!snap) {
this.meterPercent *= 1 + delta / 3;
// 一开始的时候用于下一次计算的百分比是小于这一次的,但是如果经过计算.下次的百分比这次的还小的话,则百分比不变,如果比这次的还大的话,则等于这次的百分比.
// 因为乘于的系数是大于1的,所以meterpercent的值会一直变大.
if (this.meterPercent > this.meterPercentGoal) {
this.meterPercent = this.meterPercentGoal;
}
}
else {
this.meterPercent = this.meterPercentGoal;
}
}
else {
//当用于计算的百分比比这次的百分比要大的时候,则应该进行下调的操作.所以会用减法,乘于的系数小于1.
if (this.meterPercent > this.meterPercentGoal) {
if (!snap) {
this.meterPercent *= 1 - delta;
//如果经过计算后的百分比比这次要小了(其实就是减的多了),则等于这次的. 如果还是大的话,则不变.
if (this.meterPercent < this.meterPercentGoal) {
this.meterPercent = this.meterPercentGoal;
}
}
else {
this.meterPercent = this.meterPercentGoal;
}
}
}
}