Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/html/69.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript HTML5画布中的大型2D世界渲染_Javascript_Html_Canvas_Html5 Canvas - Fatal编程技术网

Javascript HTML5画布中的大型2D世界渲染

Javascript HTML5画布中的大型2D世界渲染,javascript,html,canvas,html5-canvas,Javascript,Html,Canvas,Html5 Canvas,我有一个由随机生成的块组成的世界(黑色为开,白色为关)。放大后,它基本上看起来像白噪声。但是,每个块不是1个像素,而是40个像素并绘制为图像纹理。 我的游戏是基于摄像头的,所以你一次只能看到地图的一小部分,你必须移动角色才能探索其余部分 目前,我的游戏只是渲染画布范围内的每个图像(块纹理)。这将导致每一帧绘制80-100幅图像。虽然它在台式计算机上运行良好,但在移动设备上运行不太好 考虑到地图的外观在整个游戏中不会改变,我想尝试一种不同的方法。我创建了一个世界大小的画布,最终达到1600x240

我有一个由随机生成的块组成的世界(黑色为开,白色为关)。放大后,它基本上看起来像白噪声。但是,每个块不是1个像素,而是40个像素并绘制为图像纹理。 我的游戏是基于摄像头的,所以你一次只能看到地图的一小部分,你必须移动角色才能探索其余部分

目前,我的游戏只是渲染画布范围内的每个图像(块纹理)。这将导致每一帧绘制80-100幅图像。虽然它在台式计算机上运行良好,但在移动设备上运行不太好

考虑到地图的外观在整个游戏中不会改变,我想尝试一种不同的方法。我创建了一个世界大小的画布,最终达到1600x2400像素大。我把所有的纹理都画在一块外部的隐藏画布上。这是在初始化时完成的。然后我将使用
drawImage
中的剪裁属性来获取我需要的小节。虽然它起作用了,但它非常滞后,使事情比以前更糟。此外,图像质量下降到更模糊的外观,这是不可取的


现在我正在寻找更好的方法来解决这个问题。所以我的问题是,我应该怎么做?谢谢。

还有两个想法可以提高您的绩效:

  • 检查是否渲染了整个世界,或者仅渲染了(舞台上)可见的图像。例如,将世界大小增加一倍,看看它是否会影响性能。如果只渲染相关图像,则不应该这样做

  • 用于编译应用程序。它承诺将移动设备的应用程序速度提高10倍。但是请注意,这意味着对画布周围的html有一些严重的限制


过时的答案,假设问题是由于缩小太远造成的:

在3D图形中,可以用来避免这个问题。当对象距离相机较远时,使用的图像基本上较小(即像素较少)

如果你用谷歌搜索html5 canvas 2D Mipmaps之类的东西,也许你能找到合适的东西。或者您可以自己构建一个简单的mipmapping算法


但在投入这项工作之前,请尝试一下这种方法的性能,只需使用1x1像素图像简单地更改所有块图像。可能您的性能问题不是由渲染速度慢引起的,正如您所假设的那样。学习使用探查器,如果它不能解决问题。

当你使用一个巨大的画布时,你不能确定渲染器不会加载整个纹理来渲染它的一部分。由于您看到性能大幅下降,这很可能正在发生

我会做几件事:
•仅尝试使用fillRect,看看有多少drawImage是罪魁祸首。
•尝试一次性设置所有上下文,然后仅使用具有最简单风格的drawImage:

var topLeft = { col:12, row : 6 }; // shift of the left-most rect (indexes)
context.save();
context.scale( scale, scale); 
for  column = 0 to columnSeenCount 
     for row = 0 to rowSeenCount
         image = the image of  ( topLeft.col + column , topLeft.row + row )
         context.drawImage( image, column, row) ;
context.restore(); 
这样可以避免为每个图像重新计算变换矩阵。渲染器所涉及的数学要少得多

•如果您自己绘制图像,尝试只使用圆角坐标,速度会更快。
•您还必须将刻度四舍五入,以防止出现瑕疵。您可以在1上舍入,但对于比例而言,这可能是一个太多的限制:您可以轻松地“舍入”到0.5或0.25或。。。通过这样做:

  var precision     = 2 ;     //  0 => floor ; 1 => at 0.5 ; 2 => 0.25 ; .... 
  var factor        = 1 << precision ;
  var roundedFigure = Math.floor( figure * factor) / factor ;
var精度=2;//0=>地板;1=>0.5;2 => 0.25 ; .... 

var factor=1一些问题和想法:

我想重复@gamealchesman的提示,使用
drawImage
的剪辑版本比在画布上“闪电”一个单独的平铺图像要慢。当您有如此大的地图图像时,请使用单独的图像

24000像素的宽度太大,无法包含在任何一幅图像中。

看起来你在水平平移。您可以将24000像素宽的图像分割为大小更合理的单个图像。每个图像可能是屏幕宽度的3倍。当用户平移超出当前图像的边缘时,交换图像

您使用了多少个独特的块图像块?

当您检测到移动用户时,可能会减少唯一磁贴的数量。然后将每个独特的瓷砖放在单独的图像或画布上

您的地图主要是一种瓷砖类型(例如白色/灰色)?


如果是这样的话,您可以制作一个由足够多的白色瓷砖组成的网格的单个图像,以填充整个画布。然后在必要时添加黑色瓷砖。这会将您的绘图减少到1张白色网格图像加上所有必需的黑色图像。

谢谢您的回复。我做了一些测试,确定在我的设备(Galaxy Nexus w/Chrome)上绘制图像与绘制简单矩形的速度平均要慢6 fps,所以我认为这肯定会影响性能。恐怕我不太理解您的第一个代码示例。为什么要缩放上下文?除此之外,看起来您正在单独绘制每个瓷砖,就像我现在所做的一样。如果我错了,请纠正我,但我注意到,与画布绘制相比,数学运算几乎不花费时间,因此可以忽略不计。假设我捕获了所有非整数坐标,我收到的帧速率与以前相同。是的,我目前正在为每个瓷砖纹理使用单独的图像。我将尝试分割图像。我不确定我是否提到玩家总是呆在屏幕的中心,因此世界围绕着他移动。如果玩家坐在其中一张图片的一角,我将不得不绘制并管理另外4张图片来扩展视图。我想知道这是否会导致滞后峰值或根本不值得。我不太明白你说的独特瓷砖是什么意思。我使用了大约15种不同的纹理可能性,所以最后的选项不起作用。另外,你知道图像文件类型以及它们如何影响渲染时间吗?我目前正在使用稍微透明的PNG。将