管理要在HTML5 Canvas上绘制的2D数组中的文本地图

tes*_*est 22 javascript jquery html5 canvas

所以,我正在制作一个HTML5 RPG,只是为了好玩.地图是<canvas>(512px宽,352px高| 16个瓷砖,11个瓷砖从上到下).我想知道是否有更有效的方式来绘制<canvas>.

这就是我现在的方式:

如何在地图上加载和绘制图块

地图由瓷砖(32x32)使用该Image()块绘制.图像文件通过一个简单的for循环加载并放入一个名为tiles[]PAINTED on 的数组中drawImage().

首先,我们加载瓷砖......

在此输入图像描述

以及它是如何完成的:

// SET UP THE & DRAW THE MAP TILES
tiles = [];
var loadedImagesCount = 0;
for (x = 0; x <= NUM_OF_TILES; x++) {
  var imageObj = new Image(); // new instance for each image
  imageObj.src = "js/tiles/t" + x + ".png";
  imageObj.onload = function () {
    console.log("Added tile ... " + loadedImagesCount);
    loadedImagesCount++;
    if (loadedImagesCount == NUM_OF_TILES) {
      // Onces all tiles are loaded ...
      // We paint the map
      for (y = 0; y <= 15; y++) {
        for (x = 0; x <= 10; x++) {
          theX = x * 32;
          theY = y * 32;
          context.drawImage(tiles[5], theY, theX, 32, 32);
        }
      }
    }
  };
  tiles.push(imageObj);
}
Run Code Online (Sandbox Code Playgroud)

当然,当玩家开始游戏时,它会加载他们最后离开的地图.但是在这里,它是一张全草地图.

现在,地图使用2D数组.这是一个示例地图.

[[4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 1, 1, 1, 1], 
[1, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 1], 
[13, 13, 13, 13, 1, 1, 1, 1, 13, 13, 13, 13, 13, 13, 13, 1], 
[13, 13, 13, 13, 1, 13, 13, 1, 13, 13, 13, 13, 13, 13, 13, 1], 
[13, 13, 13, 13, 1, 13, 13, 1, 13, 13, 13, 13, 13, 13, 13, 1], 
[13, 13, 13, 13, 1, 13, 13, 1, 13, 13, 13, 13, 13, 13, 13, 1], 
[13, 13, 13, 13, 1, 1, 1, 1, 13, 13, 13, 13, 13, 13, 13, 1], 
[13, 13, 13, 13, 13, 13, 13, 1, 13, 13, 13, 13, 13, 13, 13, 1], 
[13, 13, 13, 13, 13, 11, 11, 11, 13, 13, 13, 13, 13, 13, 13, 1], 
[13, 13, 13, 1, 1, 1, 1, 1, 1, 1, 13, 13, 13, 13, 13, 1], 
[1, 1, 1, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 1, 1, 1]];
Run Code Online (Sandbox Code Playgroud)

我使用简单的if结构获得不同的地图.一旦上面的2d数组return,每个数组中的相应数字将根据Image()存储的内部进行绘制tile[].然后drawImage()会发生,并根据油漆xy和时间它通过32画上正确的x-y坐标.

如何进行多个地图切换

随着我的游戏,地图有五件事情来跟踪:currentID,leftID,rightID,upID,和bottomID.

  • currentID:所在地图的当前ID.
  • leftID:currentID退出当前地图左侧时要加载的ID .
  • rightID:currentID退出当前地图右侧时要加载的ID .
  • downID:currentID退出当前地图底部时要加载的ID .
  • upID:currentID退出当前地图顶部时要加载的ID .

一些需要注意的:如果有一个leftID,rightID,upID,或bottomID不特定的,这意味着他们是一个0.这意味着他们不能离开地图的那一边.它只是一种无形的封锁.

因此,一旦一个人离开地图的一侧,取决于他们退出的地方...例如,如果他们退出底部,那么bottomIDmap加载的数量,从而在地图上绘制.

这是一个代表性的.GIF,可以帮助您更好地可视化:

在此输入图像描述

正如你所看到的,迟早会有许多地图,我会处理很多 ID.这可能会让人感到困惑和忙乱.

显而易见的优点是它一次加载176个图块,刷新一个小的512x352画布,并且一次处理一个图.可以理解的是,MAP ids在处理许多地图时,有时可能会感到困惑.

我的问题

  • 这是一种存储地图的有效方式(考虑到瓷砖的使用),还是有更好的方法来处理地图?

我正在思考一张巨大的地图.地图大小很大,它只是一个2D数组.但是,视口仍然是512x352像素.

这是另一个.gif我(为这个问题)帮助可视化:

在此输入图像描述

对不起,如果你不懂我的英语.请问任何你无法理解的事情.希望我说得很清楚.谢谢.

Sim*_*ris 16

那么这里有一些东西,所以我会按顺序回复它们.


... 521单独的PNG文件?

在此输入图像描述

用一个.只有一个.也许,上衣.考虑一下,你是否让每个客户做500个GET请求只是为了获得游戏的瓷砖?那是疯子.

几乎每个主要站点都使用精灵映射来减少请求.例如,Youtube将这一个图像用于其所有按钮:

在此输入图像描述

你也应该这样做.


从性能角度来看,将画布用作视口的概念是正确的.绝对不要让它变得比它需要的更大!


至于你的地图性能问题,巨型阵列应该可以开始.这是处理它的好方法,除非你的话非常非常大,否则我不会费心去探索其他选项.如果它是巨大的,你可以拥有400x400(左右)的世界"块",当你来到第400行时,你开始使用下一个数组的第0行.当然,当你的英雄位于旧的四角位置时,任何时候"使用中"的阵列都将是四个.

球员的位置并不难.如果他在瓦片822,20那将意味着他在(2, 0)(由我们开始(0, 0))的大块中.具体来说,他将在第22块,第20块中.没有复杂的数学,没有ID.没有必要跟踪ID.您甚至不必跟踪哪个块是最后一个块.你可以知道总地图大小是(例如)1200x1200,如果他试图移动到(1201,50),你甚至不必看是否(4, 0)存在块.你知道他不能移动那里,地图只有1200瓦宽!

在你不得不担心这个特定阵列之前,性能应该是正常的,并且在很大程度上依赖于大量的其他东西.我的建议是担心在担心性能之前制作游戏.一旦游戏变慢,重新访问性能.

一旦你达到性能,我会首先担心除了这个问题之外的所有事情.在帆布游戏中,它不太可能成为瓶颈.从数组中读取很快.已经在内存中的大型阵列应该很快.这里不应该是一个问题,我不会花时间预测一个直到它实际上提出了自己.


编辑:与播放器一起移动的视口示例:http://jsfiddle.net/kmHZt/10/