传统的游戏开发,使用的就是位图引擎,所以开发者们都对位图的处理十分注意。
其中在Flash游戏开发过程中同样体现这一点的就是,在copyPixels()函数执行前后,先后执行lock()函数和unlock()函数,以提高效率。
但是为什么这样做呢?这样做能提高游戏哪方面的性能呢?背后有蕴含着什么道理呢?
带着种种疑问,今天正研究这个问题。下面请读者跟着我的步伐,来探个究竟。(PS:如果你跟我一样野研究这个问题,也有自己的一番见解,欢迎一起探讨。)
1.首先,位图处理提高性能,马上想到的是渲染效率的提高。
于是写了段代码,连续n帧执行copyPixels()的代码,而且在第一帧测试之前,通过lock()函数,锁住bitmapData,在最后第n帧执行完之后执行函数unlock()。并计算出这n帧过程中的渲染用时。
结果:这样处理,在执行完n帧之后,才更新bitmap。相比起不进行lock()锁定,渲染用时的确短了,帧频也稳定。
分析:由于整过过程都进行了lock()锁定(到了最后才解锁),所以bitmap到了最后才会有变化,屏幕没有更新,肯定就不用渲染重绘,所以帧频稳定也是非常正常的。
问题:问题是,实际使用过程中,我们根本很少可能存在:多帧不用更新bitmap的情况。如果有这种需求,我不如直接在需要更改bitmap的情况下,直接替换bitmap的bitmapData属性算了。
代码:下面是每帧的代码。(记得,在监听Enter Frame事件之前,执行bmp1.lock())
private function onEnterFrame(event:Event):void
{
count++;
if (count > 100)
{
removeEventListener(Event.ENTER_FRAME, onEnterFrame);
trace(getTimer() – oldTime);
bmp1.unlock();
return;
}
for (var i:int = 0; i < 100; i++)
bmp1.copyPixels(bmp2, new Rectangle(0, 0, 800, 800), new Point(0, 0));
}
2.后来估计,是提高了bitmapData修改时,代码执行的效率。
帮助文档提到:“要提高性能,请在对 setPixel() 或 setPixel32() 方法进行多次调用之前和之后使用此方法及 unlock() 方法。” 可以看出,unlock()方法锁定了位图,可以让给位图作多次写入操作,有很好的性能提高。
于是写了一段代码,只在第一帧上执行(而且官方的demo也是在一帧上执行的)。测试其代码执行的耗时,并跟没有进行锁定的情况对比。
结果:测试差不多一千万次,提高了1秒的时间,看上去很少,但是你要知道,我们做的操作只是,把一个像素,写入一个位图。而且,500 * 500 的图片已经有25万个像素。(测试过getPixel()和getPixel32(),锁不锁定,差别不大)
猜想:给位图写入像素,如果不锁定,那么,每次写入一个像素,都要访问内存的位图对应的地址,需要多次写入内存,降低效率。但是如果锁定了,更新的内容不用立即被渲染,像素的写入操作,首先统一写入到一个cache缓存区,然后在unlock()解锁后,再统一写入内存,只访问内存一次,较少写入次数。
代码:
bmp1.unlock();
var l:uint = 9999999;
oldTime = getTimer();
while (l–)
{
bmp1.setPixel(bmp2.width * Math.random(), bmp2.height * Math.random(), 0xFF0000);
}
trace(“没锁:” + (getTimer() – oldTime));
bmp1.lock();
l = 9999999;
oldTime = getTimer();
while (l–)
{
bmp1.setPixel(bmp2.width * Math.random(), bmp2.height * Math.random(), 0xFF0000);
}
trace(“锁了:” + (getTimer() – oldTime));
附:今天测试过程中,发现,某些电脑的某些Flash播放器,执行lock()函数没效果,而且不止一台电脑这样,希望知情者,能告知一下。