游戏开发中的Flash性能:本地渲染 vs BitmapData帧缓冲区

20

我正在开发一个2D射击游戏,有很多对象和激进的滚动。

问题: 哪种方式更好?

选择1 - 使用本机Flash渲染:

  • 从Bitmap派生游戏对象,使用现有的x、y、width、height、bitmapData
  • 将所有对象作为子项UIComponent.addChild(...)添加到屏幕上
  • 使用"scrollRect"剪裁可见区域

选择2 - 使用"位图+copyPixels"编写自定义渲染

  • 使用自己的游戏对象和x、y、width、height、bitmapData
  • 将Bitmap添加到屏幕上,并从中获取bitmapData
  • 每个ENTER_FRAME重新绘制:bitmapData.lock(),迭代游戏对象并将其copyPixels()到bitmapData中,然后bitmapData.unlock()
  • 自定义剪裁:不呈现屏幕外的对象

在这个问题中,一些人抱怨"位图+copyPixels()"太慢了。

实验: 我已经实现了这两种技术:

请尝试它们并告诉我哪一个更好(更快、更流畅、占用CPU更少)。

等到至少有250个敌人(屏幕上方的计数器)。
更新: 尝试打开任务管理器(或$top)并查看整体CPU使用率

更新2: 我已经改变了代码,现在小怪物产生得更快了。


3
如果你使用Mr. Doob的SWF内置分析工具,你就不必猜测内存使用量或帧率:http://code.google.com/p/mrdoob/wiki/stats - HanClinto
5个回答

4
我发现自定义(位图渲染)版本要快得多,这是我预料到的。
Flash的DisplayList旨在考虑到DisplayObjects中的许多差异,因此不会是最有效的路线(除非您在AS3中考虑了所有这些差异,否则您将输给本机代码)。
例如,对于平铺渲染(其中您正在为平铺进行copyPixels),自定义位图渲染器将比在DisplayList上具有数百个DisplayObjects要快得多。您还可以使用专门的剪辑器来丢弃平铺,而Flash最终会执行非常通用的边界框计算和测试。
关于差异,例如,在您的自定义版本中,“building”精灵随着角色移动而摇晃,可能是由于您的代码中的float-to-int转换或四舍五入而不是向下舍入。

4
更新:感谢高压版本。再次奔跑时,我并没有真正看到区别。但是我聪明地发现,“r”会放置炮塔,当我放置了20-30个炮塔时,本机版本比手动版本略慢,所以也许我错了。(我没有看到内存使用方面的差异。)仍然觉得本地执行操作应该有更快的潜力,但可能需要对某些不透明的内容进行专门处理。
既然这已经被接受了,我会添加一条说明来明确我在对不同答案发表评论时所说的话:如果您所有的资产本身都是位图,则像HanClinto指出的那样,手动合成它们比创建本地对象并让Flash工作更快,因为它消除了与显示对象相关的开销,例如事件结构。
然而,可能存在手动完成任务更胜一筹的情况,例如如果您有需要渲染为位图的向量内容、大量的动画精灵,或者如果您需要检测演员的鼠标事件(如果您自己进行合成,则可能需要手动且痛苦)。
因此,如果您不需要执行任何会减慢手动合成速度的操作,那么手动合成似乎绝对是最佳答案,如果您需要执行此类操作,则尝试两种方法是绝对确定的最佳方式。(还可以使用混合模型,其中制作需要鼠标事件的本地对象的一层,并使用手动合成的位图覆盖或下层。)

2

如果您在屏幕上处理数百或数千个对象(例如强烈的粒子效果),那么使用CopyPixels可以获得更好的性能。

很大程度上这取决于您要做什么,对吧?


好的,有人必须要做“数学运算”:无论是你的代码还是Flash播放器。 两个版本的SWF都使用位图。顺便问一下,哪个SWF更好? - oshyshko
1
HanClinto,为什么你会期望 CopyPixels 有更好的表现? - fenomas
1
@oshyshko: 对于我来说,#2表现更好,但没有FPS计数器很难给您提供良好的度量标准。 您是否尝试使用像Mr. Doob这样的性能测量小部件?http://code.google.com/p/mrdoob/wiki/stats @fenomas:仅因为DisplayObject是一个相当沉重的类。它有很多检查花哨的东西,您可能不会使用,如果您自己管理所有渲染代码,就可以自由地削减大量垃圾。 根据我的经验,Flash显示堆栈实际上并不是特别高效的(尤其是对于成千上万个对象,例如大型平铺图)。 - HanClinto
我明白你的意思,如果你所有的资源都是位图,那么你将会绕过很多东西。上一次我做类似的事情时,有许多通用的显示对象需要在合成之前进行渲染,因此据我回忆,本地方法更为优越。 - fenomas
@fenomas:抱歉回复晚了——不确定为什么之前我没有想到,但你在示例中可能缺少的一件事是位图缓存。DisplayObject可以对其对象进行缓存,以便它不必在每帧重新计算过滤器,但你处理事情的方式可能绕过了缓存,并导致减速。我不确定,这只是一个想法。 - HanClinto

1

Flash可以在现代PC或Mac上本地处理数百个精灵而不会失去性能,因此我建议使用显示对象。


0

我有一台低端笔记本电脑,Intel Mobile 1.6Ghz/512MB,Firefox 3.5.x,Flash10.0.32.18,WinXP

我可以清楚地看到很大的差异。

原生版本:不到10秒就达到CPU99%,移动时会出现卡顿。 自定义版本:保持在以下范围内

顺便问一下,有没有可能得到示例代码作为练习。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接