我目前正在为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”功能的延迟调用,但这也没有产生明显的差异。
我有以下问题:
一些我研究过的问题的链接,但到目前为止没有结果:
最佳答案
您的主要问题似乎是用来绘制到 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/