2016-04-27 75 views
0

似乎有一些关于这从博客到博客,视频到论坛到论坛的不同意见。这是专门针对画布标签的2D上下文,而不是WebGL。我知道WebGL会给我更好的表现,但我的目标是了解canvas标签在2D上下文中的工作方式。帆布游戏开发和表现

我听说在“虚拟”的屏幕外画布中预先渲染对象可能是最好的表现,这有助于看到浏览器不会真正地绘制它。然后,人们说使用“getImageData”从该画布中获取数据,根据我的理解,该数据返回base64代码,您可以将其应用于使用“putImageData”添加到DOM的画布。这不会是一个巨大的性能打击?

我应该在这个虚拟画布上渲染游戏的整个视图,然后在循环内部使用此方法将其显示为可见视图?

回答

1

是的,你可以。我建议在游戏循环的draw()部分中使用requestAnimationFrame(),将所有单独的对象绘制到屏幕外Canavs上,然后将图像放到可见的画布上。虽然这看起来可能会影响性能,但是当您绘制了很多对象时,get/put图像的这种开销实际上可以忽略不计。

+0

所以你说的是,如果我制作类似RPG和一些不同的瓷砖,我应该将它们全部渲染到屏幕外的画布上,然后从该画布获取数据并将它们放到可见区域? –

+1

是的:)画布上放置的每个图块都有一个小的开销,因此当您在屏幕外缓冲区上绘图时,它更快,因为它不需要绘制到内存和屏幕上,它只是将其存储到内存中。 –

+0

多个画布会对游戏开发更有益吗?一个用于瓷砖,一个用于我的主要角色,例如? –

2

画布只是一个图像,从我的经验来看,使用画布或图像在性能方面没有区别。

离线或在画布上没有什么不同,他们都会尽可能利用GPU。

使用context.getImageData()context.createImageData()context.putImageData()应避免实时渲染,它并不需要GPU和你做它将在主内存的Javascript进行任何处理的优势。虽然数据存储在一个类型数组Uint8ClampedArray中,并且可以转换为任何类型的类型数组,例如Uint32Array,允许您使用一个变量处理单个像素,而不是4.还有许多用于类型化数组的原生函数,提供比标准Javascript数组更快的数组操作。

图像的限制因素(包括画布作为图像)是可用GPU RAM的数量,当超过可用RAM的数量时,浏览器将根据需要开始将图像交换到GPU RAM中,阻碍了GPU的渲染能力,与正常的RAM访问相比,从主RAM到GPU RAM的传输速度较慢。发生这种情况时,您将立即看到帧速率的损失。由于浏览器可以运行的平台种类繁多,并且无法了解机器功能,所以在发布实时应用程序时应该小心。

如果您已经为高端桌面机器编写了高分辨率图像的游戏,它在平板电脑和低端笔记本电脑上表现不佳。为了缓解这个问题,下载图像以匹配屏幕分辨率。在1/8分辨率的设备上使用招聘背景图片会给硬件带来不适当的压力。设备是用来处理屏幕的分辨率的,经过这个分辨率会产生很大的不必要的性能影响。这是您可以使用屏幕外画布以设备原始分辨率呈现图像,然后转储原始人员图像的位置。质量不会有任何损失,但性能会有很大的提高,从而将无法播放的东西变成可播放的东西。这适用于所有图形资源。切勿以高于所用设备的分辨率存储和使用图像。

由于您可以使用画布进行多种操作,因此找出最佳运行方式的最佳方法就是进行实验。监视帧速率并尝试不同的方法解决问题。如果帧速率提高,你已经找到了一个更好的做事方式,如果帧速率下降,那么你使用了错误的方法。

+0

这几乎违背了大多数人在网上发表的言论。我认为这是有益的唯一方法是使用不移动的地图。一旦角色到达屏幕边缘,就会进入下一个角色。另外,您在帖子中提出的声明的参考位置在哪里? –

+0

@CalebPrenger我不需要保护,任何拥有浏览器和一点时间的人都可以测试画布的性能。只需加载图像,创建画布并渲染它们。看看你可以渲染多少帧速率下降,这就是你将如何找到什么有效,什么没有。现实情况是,大多数画布性能问题与画布无关,这是糟糕的JavaScript编码实践,直到性能问题才会变得明显,那么画布就会受到指责。 – Blindman67

+0

我不认为你理解多个画布的重点。一个是背景,大多数情况下我不需要重画。上面那个将是我的精灵,我需要重绘。我不会重绘整个画布,尽管我只会重绘我的角色以前所在的部分。当然,在循环中使用getImageData和putImageData画布会让游戏停滞不前。这不是我所能理解的。 –