管理要在HTML5画布上绘制的2D数组中的文本映射 [英] Managing text-maps in a 2D array on to be painted on HTML5 Canvas

查看:131
本文介绍了管理要在HTML5画布上绘制的2D数组中的文本映射的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



现在:



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



地图由图块32x32)使用 Image()件。图像文件通过一个简单的加载到循环,并放入一个名为 tiles [] drawImage()



首先,我们加载图块...



>



  //设置&绘制地图图片
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){
//加载所有图块...
//我们绘制地图
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);
}

当然,当玩家开始游戏时, 。但在这里,它是一个全草地图。



目前,地图使用二维数组。这是一个示例地图。

  [[4,1,4,1,4,1,4,1,4,1 ,4,1,1,1,1,1,1],
[1,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13 ],
[13,13,13,13,1,1,1,1,13,13,13,13,13,13,13,1],
[13,13,13 ,13,1,13,13,13,13,13,13,13,13,13,13,1,13],
[13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,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,13,13,13,13,13,13,13,13,13,13,1,13],
[13,13,13,13,13,11,11,11] ,13,13,13,13,13,13,13,1 3],
[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,13,1,1,1]];



如果结构体。一旦上面的2d数组 return ,每个数组中的相应数字将根据 Image() tile [] 。然后 drawImage()将根据 x y 并乘以 32 绘制正确的 xy 坐标。



如何进行多个地图切换



在我的游戏中,地图有五件事要记录: currentID leftID rightID upID bottomID




  • currentID:的地图。

  • leftID:当您退出左侧的
    currentID 当前地图。

  • rightID:当您退出时, currentID b $ b当前地图。

  • downID:当您在
    底部退出时要载入的 currentID 当前地图。

  • upID:
    退出时, currentID 当前地图。



注意事项:如果 leftID rightID upID bottomID 不是特定的, a 0 。这意味着他们不能离开地图的那一边。这只是一个看不见的封锁。



所以,一旦有人离开地图一侧,取决于他们离开的地方...例如,如果他们从底部退出, bottomID 将加载映射的数字,并在地图上绘制。



以下是一个具有代表性的.GIF来帮助您更好地可视化:





正如你可以看到的,早晚有很多地图我会处理很多 ID。这可能会有点混乱和忙碌。



显而易见的优点是,它一次加载176个图块,刷新一个小的512x352画布,并处理一个地图。



我的问题



ul>
  • 这是一种有效的方式来存储地图(给定了瓷砖的使用),还是有更好的方法来处理地图?



  • 我正在沿着一张巨型地图的线条思考。地图大小很大,它都是一个2D数组。但是,视口仍是512x352像素。



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





    对不起,如果你不明白我的英语。请问你有什么麻烦理解。希望我明白了。感谢。

    解决方案

    这里有几件事情,所以我会依次回应。






    ... 521 SEPARATE PNG FILES?





    使用一个。只有一个。也许,顶部。想想,你是让每个客户端都获得500 GET请求,只是为了获得游戏的瓦片?这是bonkers。



    几乎每个主要网站都使用spritemaps来减少请求。例如,Youtube使用这个图片的所有按钮:





    您也应该这样做。






    从性能角度看,使用画布作为视口的概念是正确的。






    至于你的地图性能问题,巨型数组应该只是开始好。这是一个很好的处理它的方式,我不会打扰探索其他选项,除非你的话是非常,非常大。如果它是巨大的,你可以有块的世界是400x400(左右),当你来到第400行,你开始使用下一个数组的第0行。最多的数组在使用在任何时候将是四,当然,当你的英雄将是一个好的老四角排序的位置。



    玩家位置不会很难。如果他在瓦片822,20那意味着他在由(2,0)代表的块中(如果我们从 0,0))。具体来说,他会在这块大块22,20中。没有复杂的数学,没有ID。没有必要跟踪ID。你甚至不必跟踪哪个块是最后一个块。你可以知道总地图大小是(例如)1200x1200,如果他试图移动到(1201,50),你甚至不必看看chunk (4,0)存在。你知道马上他不能移动,地图只有1200块宽!



    性能应该是罚款的方式,将真正取决于大量的其他事情之前你不得不担心这个特定的数组。我的建议是担心做游戏之前担心性能。



    一旦达到效果之后,除了 这个问题,我先担心一切。在画布游戏中,它真的不可能成为瓶颈。从数组读取速度快。已经在内存中的大型数组应该是快的。有< em>不应该是一个问题,我不会花时间预测一个,直到它实际上呈现自己。






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


    So, I'm making a HTML5 RPG just for fun. The map is a <canvas> (512px width, 352px height | 16 tiles across, 11 tiles top to bottom). I want to know if there's a more efficient way to paint the <canvas>.

    Here's how I have it right now:

    How tiles are loaded and painted on map

    The map is being painted by tiles (32x32) using the Image() piece. The image files are loaded through a simple for loop and put into an array called tiles[] to be PAINTED on using drawImage().

    First, we load the tiles...

    and here's how it's being done:

    // 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);
    }
    

    Naturally, when a player starts a game it loads the map they last left off. But for here, it an all-grass map.

    Right now, the maps use 2D arrays. Here's an example map.

    [[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]];
    

    I get different maps using a simple if structure. Once the 2d array above is return, the corresponding number in each array will be painted according to Image() stored inside tile[]. Then drawImage() will occur and paint according to the x and y and times it by 32 to paint on the correct x-y coordinate.

    How multiple map switching occurs

    With my game, maps have five things to keep track of: currentID, leftID, rightID, upID, and bottomID.

    • currentID: The current ID of the map you are on.
    • leftID: What ID of currentID to load when you exit on the left of current map.
    • rightID: What ID of currentID to load when you exit on the right of current map.
    • downID: What ID of currentID to load when you exit on the bottom of current map.
    • upID: What ID of currentID to load when you exit on the top of current map.

    Something to note: If either leftID, rightID, upID, or bottomID are NOT specific, that means they are a 0. That means they cannot leave that side of the map. It is merely an invisible blockade.

    So, once a person exits a side of the map, depending on where they exited... for example if they exited on the bottom, bottomID will the number of the map to load and thus be painted on the map.

    Here's a representational .GIF to help you better visualize:

    As you can see, sooner or later, with many maps I will be dealing with many IDs. And that can possibly get a little confusing and hectic.

    The obvious pros is that it load 176 tiles at a time, refresh a small 512x352 canvas, and handles one map at time. The con is that the MAP ids, when dealing with many maps, may get confusing at times.

    My question

    • Is this an efficient way to store maps (given the usage of tiles), or is there a better way to handle maps?

    I was thinking along the lines of a giant map. The map-size is big and it's all one 2D array. The viewport, however, is still 512x352 pixels.

    Here's another .gif I made (for this question) to help visualize:

    Sorry if you cannot understand my English. Please ask anything you have trouble understanding. Hopefully, I made it clear. Thanks.

    解决方案

    Well there's a few things here so I'll respond to them in order.


    ...521 SEPARATE PNG FILES?

    Use one. Just one. Maybe six, tops. Think about it, you're making every client do 500 GET requests just to get the tiles for the game? That's bonkers.

    Almost every major site ever uses spritemaps to reduce requests. Youtube, for instance, uses this one image for all of its buttons:

    You should do the same.


    Your concept of using the canvas as a viewport is correct from a performance perspective. Definitely don't make it bigger than it needs to be!


    As to your map performance question, giant arrays ought to be just fine to start. This is a fine way of dealing with it and I wouldn't bother exploring other options unless your word is very, very large. If it is massive, you could have "chunks" of the world that are 400x400 (or so) and when you come to the 400th row you start to use row 0 of the next array. The most arrays "in use" at any time will be four, of course, when your hero would be on a good old four corners sort of location.

    Player location wouldn't be hard. If he was at tile 822, 20 that would mean he is in the chunk represented by (2, 0) (if we're starting from (0, 0)). Specifically, he'd be in tile 22, 20 of that chunk. No complex math, no ID's. There is no need to keep track of ID's. You don't even have to keep track of which chunk is the last chunk. You can just know that the total map size is (say) 1200x1200, and if he tries to move to (1201, 50), you don't even have to see if chunk (4, 0) exists. You know right away he can't move there, the map is only 1200 tiles wide!

    Performance should be fine either way and will really depend on a large number of other things before you have to worry about this particular array. My advice is to worry about making the game before worrying about performance. Revisit performance once the game gets slow.

    Once you get to performance, I would worry about everything except this issue first. In a canvas game its really unlikely to be the bottleneck. Reading from arrays is fast. Large arrays already in memory ought to be fast. There shouldn't be a problem, and I wouldn't spend time anticipating one until it actually presents itself.


    EDIT: Example of viewport moving with player: http://jsfiddle.net/kmHZt/10/

    这篇关于管理要在HTML5画布上绘制的2D数组中的文本映射的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆