ENTER_FRAME中删除自己导致闪烁bug的解决方案
在lufylegend.js中运行以下代码会出现闪烁的问题:LInit(50, "mygame", 600, 480, main);var img = null;
var addIndex = 40, addSpeed = addIndex;
function main () {
var loader = new LLoader();
loader.addEventListener(LEvent.COMPLETE, demoInit);
loader.load("./gold_ingot.png");
}
function demoInit (e) {
img = e.target;
var layer = new LSprite();
addChild(layer);
layer.addEventListener(LEvent.ENTER_FRAME, function (e) {
var s = e.currentTarget;
if (addIndex++ > addSpeed) {
addIndex = 0;
var item = new Item();
s.addChild(item);
}
});
}
function Item () {
var s = this;
LExtends(s, LSprite, []);
var bmpd = new LBitmapData(img);
var bmp = new LBitmap(bmpd);
s.addChild(bmp);
s.addEventListener(LEvent.ENTER_FRAME, s.loop);
}
Item.prototype.loop = function(e) {
var s = e.currentTarget;
s.x += 3;
if (s.x > LGlobal.width) {
s.remove();
}
};测试地址:http://wyh.wjjsoft.com/test/blink_bug/index.html
出现这类问题是因为调用remove函数删除自己破坏了父元素显示列表。ENTER_FRAME事件是在LSprite对象渲染完毕时调度的,子LSprite元素渲染函数是在父元素遍历显示列表childList时调用的,所以在这里面删除自己会导致父元素还未完成遍历显示列表,显示列表就已经被破坏了。为此,我查看了lufylegend里LSprite的ll_show方法:_ll_show : function (c) {
var s = this;
s.graphics.ll_show();
LGlobal.show(s.childList);
s._ll_debugShape();
},可见,要解决这个问题,可以通过更改LGlobal.show方法来实现,原来的LGlobal.show的代码如下:LGlobal.show = function (s) {
for (var i = 0, l = s.length; i < l; i++) {
if (s && s.ll_show) {
s.ll_show();
}
}
};由于用变量l保存了列表的length属性,删除自己时length改变了,但是l并没有改变,所以就出现遍历错误的问题。
更改后的代码如下:LGlobal.show = function (s) {
var list = s.slice(0, s.length);
for (var i = 0, l = list.length; i < l; i++) {
if (list && list.ll_show) {
list.ll_show();
}
}
};
更改后这个问题基本上就解决了
测试地址:http://wyh.wjjsoft.com/test/blink_bug/index2.html
除了上述的方法,还可以用一个数组保存需要删除的对象,在父元素的ENTER_FRAME事件中,清除这个列表里保存的对象,并清空这个数组。
这样做虽然能解决你说的这个问题,但是每个显示对象都会每次拷贝(s.slice)自己的子对象数组,这样也会导致另外两个问题
第一个,就是内存使用量增加,这个影响倒不大
第二个,就是导致效率降低,画面上对象越多桢率越高,就会越明显,(数组自带的函数操作效率不高,如果想让效率更高,在高频率操作中,尽量避免数组的操作),虽然不能说这个非常严重,但是效率本来就是一点点来提升的,如果不注重每一个细节,积少成多,以后效率就会越来越慢,而且也不容易再改回来了
还是多谢了,这个地方我来想办法吧
除了上述的方法,还可以用一个数组保存需要删除的对象,在父元素的ENTER_FRAME事件中,清除这个列表里保存的对象,并清空这个数组。
如果开发中,真的碰到了这个问题,这个临时方案是可行的,因为不会影响到其他显示对象的列表操作 lufy 发表于 2015-2-27 17:08 static/image/common/back.gif
这样做虽然能解决你说的这个问题,但是每个显示对象都会每次拷贝(s.slice)自己的子对象数组,这样也会导 ...
想了想,解决起来也并不太复杂,此问题1.9.8中解决 lufy 发表于 2015-2-27 17:53 static/image/common/back.gif
想了想,解决起来也并不太复杂,此问题1.9.8中解决
能说说思路吗? 本帖最后由 yorhomwang 于 2015-2-27 18:27 编辑
lufy 发表于 2015-2-27 17:53 static/image/common/back.gif
想了想,解决起来也并不太复杂,此问题1.9.8中解决
准备两套数组? yorhomwang 发表于 2015-2-27 18:25 static/image/common/back.gif
准备两套数组?
准备两套数组一样是浪费内存阿
还是等过两天新版本更新后直接看代码吧
页:
[1]