做游戏过程中用好的逻辑算法和实现方式的话游戏不会很卡的,但是如果你有一个极端的需求,比如同时创建1000个对象,创建的过程肯定是会有卡顿的,这时候该怎么办呢?
这时候就不要犹豫,祭出你的大杀器——分帧运算吧。分帧运算的原理就是把原本1帧需要处理完的逻辑拆分为多帧分别处理,每帧执行消耗的时间短了,也就不会有卡顿了。代码实现思路:做一个“缓存池”存放需要大量处理逻辑,缓存池开始工作以后记录一下处理池里的逻辑消耗的时间,超过这个执行时间的“阈值”以后就休息等待下一帧,循环往复一直到“池”里的内容处理完。
用《消灭方块》做测试的测试结果如下:
测试条件:
把创建的方块数量改成50*70=3500个
<span style="white-space:pre"> </span>public static TYPE_COLUMN:number[] = [50, 5, 6];
<span style="white-space:pre"> </span>public static TYPE_ROW:number[] = [70, 7, 8];
把addChild方块的代码注释掉,去除渲染对测试结果的影响:
/* 添加方块到指定单元格*/
public addBlockAt(index:number):void
{
var block:Block = this.getNewBlock();
this._blocks[index] = block;
var pos:egret.Point = this.getPosByIndex(index);
block.x = pos.x;
block.y = pos.y;
<span style="white-space:pre"> </span>//this._container.addChild(block);
block.playFadeInAnimation();
}
准备条件做完,开始测试:
创建3500个方块,开始游戏瞬间帧数降低到16。
好了,看看使用分帧运算代码后的效果吧:
53帧!是不是很吃惊呢。控制台输出的结果可以看到把这一帧做完的事情分成了81帧处理完。
好了,贴代码,写文章的时候临时写的,想更好用的话还要自己去拓展功能哦~
class DeleyOptManager
{
private TIME_THRESHOLD:number = 3;<span style="white-space:pre"> </span>//每帧运算逻辑的时间阈值,执行代码超过这个时间就跳过到下一帧继续执行,根据实际情况调整,因为每一帧除了这里的逻辑还有别的逻辑要做对吧
private _delayOpts:any[];
private static _instance:DeleyOptManager;
public constructor()
{
this._delayOpts = [];
}
public static i():DeleyOptManager
{
if(!this._instance)
this._instance = new DeleyOptManager();
return this._instance;
}
public addDeleyOptFuncition(thisObj:any, fun:Function, funPara?:any, callBack?:Function, para?:any):void
{
this._delayOpts.push({"fun":fun, "funPara":funPara, "thisObj":thisObj, "callBack":callBack, "para":para});
egret.Ticker.getInstance().register(this.runCachedFun, this);
}
private runCachedFun(f:any):void
{
if(!this._delayOpts.length)
egret.Ticker.getInstance().unregister(this.runCachedFun, this);
var timeFlag = egret.getTimer();
var funObj:any;
while(this._delayOpts.length)
{
funObj = this._delayOpts.shift();
if(funObj.funPara)
funObj.fun.call(funObj.thisObj, [funObj.funPara]);
else
funObj.fun.call(funObj.thisObj);
if(funObj.callBack)
{
if(funObj.para)
funObj.callBack.call(funObj.thisObj, [funObj.para]);
else
funObj.callBack();
}
if(egret.getTimer() - timeFlag > this.TIME_THRESHOLD)
break;
}
}
}