lufy's legend

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 8729|回复: 5

ENTER_FRAME中删除自己导致闪烁bug的解决方案

[复制链接]

46

主题

3

好友

1866

积分

偏将军

Rank: 4

发表于 2015-2-27 15:23:12 |显示全部楼层
在lufylegend.js中运行以下代码会出现闪烁的问题:
  1. LInit(50, "mygame", 600, 480, main);

  2. var img = null;
  3. var addIndex = 40, addSpeed = addIndex;

  4. function main () {
  5.         var loader = new LLoader();
  6.         loader.addEventListener(LEvent.COMPLETE, demoInit);
  7.         loader.load("./gold_ingot.png");
  8. }
  9. function demoInit (e) {
  10.         img = e.target;

  11.         var layer = new LSprite();
  12.         addChild(layer);
  13.         layer.addEventListener(LEvent.ENTER_FRAME, function (e) {
  14.                 var s = e.currentTarget;

  15.                 if (addIndex++ > addSpeed) {
  16.                         addIndex = 0;

  17.                         var item = new Item();
  18.                         s.addChild(item);
  19.                 }
  20.         });
  21. }

  22. function Item () {
  23.         var s = this;
  24.         LExtends(s, LSprite, []);

  25.         var bmpd = new LBitmapData(img);
  26.         var bmp = new LBitmap(bmpd);
  27.         s.addChild(bmp);

  28.         s.addEventListener(LEvent.ENTER_FRAME, s.loop);
  29. }
  30. Item.prototype.loop = function(e) {
  31.         var s = e.currentTarget;

  32.         s.x += 3;

  33.         if (s.x > LGlobal.width) {
  34.                 s.remove();
  35.         }
  36. };
复制代码
测试地址:http://wyh.wjjsoft.com/test/blink_bug/index.html

出现这类问题是因为调用remove函数删除自己破坏了父元素显示列表。ENTER_FRAME事件是在LSprite对象渲染完毕时调度的,子LSprite元素渲染函数是在父元素遍历显示列表childList时调用的,所以在这里面删除自己会导致父元素还未完成遍历显示列表,显示列表就已经被破坏了。为此,我查看了lufylegend里LSprite的ll_show方法:
  1. _ll_show : function (c) {
  2.         var s = this;
  3.         s.graphics.ll_show();
  4.         LGlobal.show(s.childList);
  5.         s._ll_debugShape();
  6. },
复制代码
可见,要解决这个问题,可以通过更改LGlobal.show方法来实现,原来的LGlobal.show的代码如下:
  1. LGlobal.show = function (s) {
  2.         for (var i = 0, l = s.length; i < l; i++) {
  3.                 if (s[i] && s[i].ll_show) {
  4.                         s[i].ll_show();
  5.                 }
  6.         }
  7. };
复制代码
由于用变量l保存了列表的length属性,删除自己时length改变了,但是l并没有改变,所以就出现遍历错误的问题。
更改后的代码如下:
  1. LGlobal.show = function (s) {
  2.         var list = s.slice(0, s.length);

  3.         for (var i = 0, l = list.length; i < l; i++) {
  4.                 if (list[i] && list[i].ll_show) {
  5.                         list[i].ll_show();
  6.                 }
  7.         }
  8. };
复制代码
更改后这个问题基本上就解决了
测试地址:http://wyh.wjjsoft.com/test/blink_bug/index2.html
除了上述的方法,还可以用一个数组保存需要删除的对象,在父元素的ENTER_FRAME事件中,清除这个列表里保存的对象,并清空这个数组。
回复

使用道具 举报

37

主题

8

好友

9305

积分

诸侯王

Rank: 15Rank: 15Rank: 15Rank: 15Rank: 15

发表于 2015-2-27 17:08:06 |显示全部楼层
这样做虽然能解决你说的这个问题,但是每个显示对象都会每次拷贝(s.slice)自己的子对象数组,这样也会导致另外两个问题
第一个,就是内存使用量增加,这个影响倒不大
第二个,就是导致效率降低,画面上对象越多桢率越高,就会越明显,(数组自带的函数操作效率不高,如果想让效率更高,在高频率操作中,尽量避免数组的操作),虽然不能说这个非常严重,但是效率本来就是一点点来提升的,如果不注重每一个细节,积少成多,以后效率就会越来越慢,而且也不容易再改回来了

还是多谢了,这个地方我来想办法吧


除了上述的方法,还可以用一个数组保存需要删除的对象,在父元素的ENTER_FRAME事件中,清除这个列表里保存的对象,并清空这个数组。

如果开发中,真的碰到了这个问题,这个临时方案是可行的,因为不会影响到其他显示对象的列表操作
不回答与技术和引擎不相关的问题
回复

使用道具 举报

37

主题

8

好友

9305

积分

诸侯王

Rank: 15Rank: 15Rank: 15Rank: 15Rank: 15

发表于 2015-2-27 17:53:31 |显示全部楼层
lufy 发表于 2015-2-27 17:08
这样做虽然能解决你说的这个问题,但是每个显示对象都会每次拷贝(s.slice)自己的子对象数组,这样也会导 ...

想了想,解决起来也并不太复杂,此问题1.9.8中解决
不回答与技术和引擎不相关的问题
回复

使用道具 举报

46

主题

3

好友

1866

积分

偏将军

Rank: 4

发表于 2015-2-27 18:24:40 |显示全部楼层
lufy 发表于 2015-2-27 17:53
想了想,解决起来也并不太复杂,此问题1.9.8中解决

能说说思路吗?
回复

使用道具 举报

46

主题

3

好友

1866

积分

偏将军

Rank: 4

发表于 2015-2-27 18:25:49 |显示全部楼层
本帖最后由 yorhomwang 于 2015-2-27 18:27 编辑
lufy 发表于 2015-2-27 17:53
想了想,解决起来也并不太复杂,此问题1.9.8中解决

准备两套数组?
回复

使用道具 举报

37

主题

8

好友

9305

积分

诸侯王

Rank: 15Rank: 15Rank: 15Rank: 15Rank: 15

发表于 2015-2-27 21:52:32 |显示全部楼层
yorhomwang 发表于 2015-2-27 18:25
准备两套数组?

准备两套数组一样是浪费内存阿
还是等过两天新版本更新后直接看代码吧
不回答与技术和引擎不相关的问题
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

防止垃圾广告,请填写任意字符

Archiver|lufy's legend

GMT+8, 2024-3-29 14:04 , Processed in 0.054722 second(s), 21 queries .

Powered by Discuz! X2.5

© 2001-2012 Comsenz Inc.

回顶部