将场景分解为多个画布或不断重绘?

问题描述:

上的JavaScript创建基于画布游戏意图我站在一个选择之前:将场景分解为多个画布或不断重绘?

我应该表现明智的把所有的东西在屏幕上发生的事情在一个帆布(所有的运动人物,精灵)和重绘例如60 FPS的恒定速率,还是应该将场景分成几个较小的画布,从而消除了对场景进行冗余重绘的需要?我甚至可以为角色的肢体创建单独的画布元素,然后通过简单地操作给定画布元素的CSS(旋转,定位,不透明度)来完成大部分动画。

对我来说,后者听起来更合理,更容易实现,但速度更快吗?另外,我不应该使用SVG,将字符和精灵作为元素保留在其中,并直接操纵其XML和CSS属性?

那么你觉得什么是最合适的解决方案,一个场景severals精灵和文字:

  • 一个画布对象重绘手动(和浪费)在FPS率
  • 几个画布元素,手动重绘以更合理的方式
  • 结构化矢量图形文件如SVG/VML通过DOM
  • 操纵

我主要关心的性能差异,但背后的逻辑代码的易读性也很有趣(我之前已经和canvas一起工作过,例如相当肯定整个画布的重画功能是一个难以维护的剧本野兽) 。

与GPU加速画布操作相比,DOM操作速度较慢,所以我会远离SVG和VML。

就结构化画布代码而言,由于玩家移动或执行了某个动作,因此无法清除并重新绘制整个画布(特别是出于性能方面的原因)。根据你在这里的描述,我猜你的游戏将是2D。这些类型的游戏非常适合分层,除非您正在做一些像Paper Mario这样相当复杂的事情。你应该从面向对象的角度来看问题,并将你的绘图过程和对象封装在适当的位置。

例如,创建一个播放器对象,该对象维护一个表示该字符的小画布。保持角色状态所需的所有逻辑都保存在对象中,并且对其进行的任何更改都不必担心游戏视觉表示的其他组件。同样,对背景,用户界面和其他任何可以抽象为图层的内容(在合理的范围内)也是如此。例如,如果您正在进行视差游戏,则可能会有一个​​,background,characteruser interface图层。

最终,您需要分别维护游戏中不同组件的状态。玩家动画,背景云移动,树木摇曳等都将由适当的对象进行管理。由于您已经有了这种类型的代码结构设置,因此将主要组件维护在单独的画布元素上并根据需要将它们组合在一起以获得更好的性能是有意义的。如果角色在具有静态背景的场景的左下角移动,则不需要重新绘制右上角(或场景的95%)。如果你正在考虑全屏功能,这绝对是一个性能问题。

+0

谢谢。这非常详尽,支持我的想法。我喜欢这个设计方法提供的抽象概念,因为我已经在原文中说过了。然而,这里要问,通过CSS绝对定位移动例如玩家瓷砖是否比GPU加速的画布重新绘制更快。我想我会去做一些测试。 :) – Witiko

+0

@Witiko不客气!我承认,我无法确定哪种方法会更快,但我倾向于认为通过CSS定位滑动玩家拼图会更快。确实,DOM操作相对较慢,但在这种情况下,我们正在讨论必须清除整个画布,然后重新绘制所有元素(背景,UI等)。对于一款小型解析游戏,可能无关紧要。对于在1080p下以30fps运行的东西,我会先尝试CSS方法。 :) – Xenethyl

编程中有一条规则,即在遇到速度问题之前,不应尝试优化某些东西。你会花更多的时间去试图找出如何以最好的方式编码的东西,而不是真正的编码,并且永远不会完成任何事情。

以固定比率在画布上绘制它们。这是如何完成的。如果你开始为每个肢体和元素创建一个画布并使用CSS来操纵它们,那么你就是在浪费画布的潜力。不妨使用图像。这就是他们在画布之前做到的。这是帆布被解决的问题。

如果您遇到速度问题,那么您可以开始锤击他们。 Check out these slides获取一些提示(related video)。 This guy's blog也有一些方便的技巧在画布上的表现。

+0

“编程中有一条规则,即在遇到速度问题之前,不应尝试优化某些内容。” - 正如我所说,这不仅仅是表现。我确信分离这些东西会使代码更加透明。 – Witiko

+0

“不妨使用图片。” - 我实际上会这样做 - 考虑将drawImage()作为SVG图像放入画布中,并将它们作为数据URI缓存以用于'drawImage()',因为一些结构和精灵非常复杂并且定义于在代码中将毫无用处(对于风格和逻辑定义的分离来说是一场噩梦)。 – Witiko

+0

那么你最了解你的项目。你总是可以尝试一些小型的测试案例,看看你最喜欢什么。 –