我目前正在为city building game项目开发一个Web客户端(HTML5和JavaScript)。客户端通过SignalR与用C#/。NET编写的Web服务器进行交互,所有游戏逻辑都驻留在该服务器上。

该实现需要相当大的 map ,该 map 由代表不同图层的一组 Canvas 元素实现。该 map 的实际绘制包括绘制25x25px的单元格,其中一些是动画的。这意味着在“2D上下文”上发生了许多小的“drawImage”调用。

当前的实现在Mozilla Firefox,Internet Explorer和Edge中运行良好且流畅。但是,它在Google Chrome上的运行速度非常慢,这很可能是由于其硬件加速渲染效果不佳的缘故。

切片单元.PNG图像的获取是通过从Web服务器下载并将它们存储在内存中的“图像”对象中来完成的。从那里,如有必要,我将它们直接绘制到 Canvas 上。 如果我当前的研究正确完成,那么这就是瓶颈所在。源“图像”对象驻留在CPU内存中,而目标Canvas元素针对GPU内存访问进行了优化,从而导致大量交换。

我尝试将“图像”对象移动到大屏幕外的“缓冲区” Canvas (足够大以至于硬件加速应该在Chrome上启动),但这不会产生明显的区别:
https://github.com/Miragecoder/Urbanization/commit/86ac62a785b233eea28c53b8a7d474ef92ffc283

我还尝试通过requestAnimationFrame实现对“drawImage”功能的延迟调用,但这也没有产生明显的差异。

我有以下问题:

  • 我正确理解问题了吗?
  • 我该怎么做才能提高Web客户端的性能?

  • 一些我研究过的问题的链接,但到目前为止没有结果:
  • HTML5 Canvas slow on Chrome, but fast on FireFox
  • https://gamedev.stackexchange.com/questions/32221/huge-performance-difference-when-using-drawimage-with-img-vs-canvas
  • https://code.google.com/p/chromium/issues/detail?id=170021
  • Google Chrome hardware acceleration making game run slow
  • 最佳答案

    您的主要问题似乎是用来绘制到 Canvas 上的不同图像对象的数量。您绝对应该使用Textureatlas,在单个图像中放置尽可能多的图形。

    然后,您应该通过指定相关的矩形,从尽可能少的主图像中渲染 Sprite :

    void ctx.drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);
    

    而不是整个图像:
    void ctx.drawImage(image, dx, dy);
    

    有关详细信息,请参见CanvasRenderingContext2D.drawImage()。这样,您可以避免过多的上下文切换。正如Blindman67所提到的,您应该注意尽可能少地在纹理图集之间进行切换-例如,您可能要对一个到canvas1的所有渲染使用一个纹理图集,对于canvas2的所有图像使用另一个纹理图集,等等。

    关于javascript - 在大 Canvas 上的Chrome中,CanvasRenderingContext2D.drawImage()非常慢,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/34240782/

    10-11 13:27