我目前正在为city building game项目开发一个Web客户端(HTML5和JavaScript)。客户端通过SignalR与用C#/ .NET编写的Web服务器进行交互,所有游戏逻辑都驻留在该服务器上。
实现需要相当大的地图,该地图由表示不同图层的一组画布元素实现。地图的实际绘图包括绘制25x25px单元格,其中一些是动画的。这意味着在< 2D背景下发生了许多小型的drawImage&#invocations'
。当前的实现在Mozilla Firefox,Internet Explorer和Edge中运行良好且流畅。然而,谷歌浏览器的速度非常慢,很可能是由于实施对其硬件加速渲染效果不佳。
获取拼贴单元.PNG图像是通过从Web服务器下载并将它们存储在内存中的图像对象中完成的。从那里,我必要时将它们直接绘制到画布上。 如果我目前的研究工作正确,那么这就是瓶颈所处的位置;源' - 对象驻留在CPU内存中,而目标Canvas-element针对GPU内存访问进行了优化,导致大量交换。
我尝试将“图像”对象移动到一个大的屏幕外缓冲区'画布(足够大,以便硬件加速应该在Chrome上启动),但这不会产生明显的差异: https://github.com/Miragecoder/Urbanization/commit/86ac62a785b233eea28c53b8a7d474ef92ffc283
我也尝试通过requestAnimationFrame实现' drawImage' -function的延迟调用,但这也没有产生明显的差异。
我有以下问题:
我研究过的问题的一些链接,但到目前为止没有结果:
答案 0 :(得分:1)
您的主要问题似乎是您用于绘制到画布的不同图像对象的数量。你绝对应该使用Textureatlas,在单个图像中放置尽可能多的图形。
然后,您应该通过指定相关的矩形从尽可能少的主图像渲染您的精灵:
void ctx.drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);
而不是整个图像:
void ctx.drawImage(image, dx, dy);
有关详细信息,请参阅CanvasRenderingContext2D.drawImage()。这样,您可以避免过多的上下文切换。正如Blindman67所提到的,你应该小心地在纹理地图集之间切换尽可能少的时间 - 例如,你可能想要使用单个纹理图集来渲染canvas1,将另一个纹理图集用于canvas2等所有图像。