关于多帧影片剪辑的bug,初始化尺寸含有随机小数

Posted on August 30, 2012

最近项目开发过程中,又遇到了一个极其棘手的bug。调试了一天,最后发现是影片剪辑的bug。

简要介绍下背景:我们要位图化UI,将swf导入,绘制舞台上所有显示对象成BitmapData,然后进行两两比较,去除重复项并共享位图数据。判断位图的重复的方式有两种,直接两两像素比较BitmapData.compare(),或者为每个位图生成唯一的CRC32验证码,两两比较验证码即可。出于性能考虑,自然是选择后者。并且直接使用CRC32验证码作为素材的导出类名,还能在像素上保证类名唯一性。起初在位图化单帧影片剪辑的时候,这个方案一直都是好用的。后来老板提出了新的需求,要求支持动画。我们就用同样的方式去位图化多帧的影片剪辑,并合并为一张大位图来比较。结果运行时bug出来了:同一个多帧的影片剪辑,每次导出的CRC32验证码都不一致。

一开始我们怀疑CRC32的像素验证生成的字符串不是唯一的。改成用BitmapData.compare()方式,测试了下,依然出现重复导出的问题,排除这个可能。

然后怀疑是BitmapData.draw(mc) 方法有bug,每次绘制的结果有细微像素差别。为此特地写了测试,输出两次绘制后的拼合大位图进行像素比较,最终发现不是像素不一致,而是尺寸有出入。拼合的大位图每次都会有2像素的差距。

接着又怀疑是Number小数相加时出现的误差,但是同样的一批小数相加,计算机总不可能出现随机吧?还是测试了下,请出了trace大法,输出了每帧绘制前mc尺寸和绘制后位图尺寸。

数据如下:

第一次导入: [第1帧]MC.width:35.7 MC.height:36.2 frameData.width:35 frameData.height:36 [第2帧]MC.width:33.25 MC.height:34.05 frameData.width:33 frameData.height:34 [第3帧]MC.width:33.95 MC.height:34.65 frameData.width:33 frameData.height:34 [第4帧]MC.width:34.6 MC.height:35.25 frameData.width:34 frameData.height:35 ……

第二次导入: [第1帧]MC.width:35.95 MC.height:36.45 frameData.width:35 frameData.height:36 [第2帧]MC.width:33.25 MC.height:34.05 frameData.width:33 frameData.height:34 [第3帧]MC.width:33.95 MC.height:34.65 frameData.width:33 frameData.height:34 [第4帧]MC.width:34.6 MC.height:35.25 frameData.width:34 frameData.height:35 ……

第三次导入: [第1帧]MC.width:32.6 MC.height:33.45 frameData.width:32 frameData.height:33 [第2帧]MC.width:33.25 MC.height:34.05 frameData.width:33 frameData.height:34 [第3帧]MC.width:33.95 MC.height:34.65 frameData.width:33 frameData.height:34 [第4帧]MC.width:34.6 MC.height:35.25 frameData.width:34 frameData.height:35 ……

这数据一出来,总算是找到bug源头了!可以明显看出:三次导入,都是第一帧的尺寸不一致,后面每次都相同了。不知道这个随机小数是如何产生的。但是根据这个规律,大胆假设了下,每次切换帧之后,尺寸是唯一的。所以我在绘制第一帧前加了一句:先mc.gotoAndStop(mc.totalFrames)再mc.gotoAndStop(1)回来绘制。输出尺寸,这次第一帧尺寸果然全都一致了,问题解决!

希望这个发现对大家的Debug经验积累有帮助。另外,要是有人知道为什么多帧影片剪辑初始化时尺寸会出现随机小数,欢迎留言告诉我,非常感谢!

[更新]

后来经过测试,发现问题是出在AIR版本的MovieClip自身上,当mc.stage==null也就是它不在显示列表里时,跳跃式来回调用mc.gotoAndStop或者gotoAndPlay()切换帧,将会导致帧图像不断重叠累积。而初始化的时候,不确定跳到那帧,所以会出现随机尺寸。终极解决方案就是,在绘制之前把mc添加到显示列表就可以了。但是这个bug只在AIR里有,Web版本里没有。所以网上一点资料都搜索不到。否则如果mc一直有这么大的bug,之前运用帧跳转绘制位图的游戏都应该会出问题了。

[更新]这个bug也被其他人发现并提交了:https://bugbase.adobe.com/index.cfm?event=bug&id=3201621