0

我正在开发一个基于浏览器的网页游戏,其中包含一个非常大的 2d 基于图块的地图。与 Tribal Wars 等游戏不同,地形不是从种子或一个大图像文件随机生成的。

我目前所做的是有一个隐藏的画布元素,其中包含一个 bmp 地图,其中每个像素代表一个图块。绿色像素代表陆地,蓝色像素代表水域,黑色像素代表地图之外的区域。

目前,我的算法将在画布中获取位图的某个矩形段,然后创建一堆大小一致的图块,这些图块可以放入更大的 div 中。瓷砖从左到右绘制,依靠相对定位和浮动:左来正确排列自己。每个图块为 30 像素 x 30 像素,在 1080p 显示器上加起来相当多的图块。

为了移动地图,用户按下箭头键移动画布中的矩形选择,然后将其全部绘制回来。

这是直接的代码:

<script>

$("#WorldMapCanvas").hide();

var canvas = document.getElementById('WorldMapCanvas');
var context = canvas.getContext('2d');
var imageObj = new Image();
imageObj.src = '../Images/MapTest3.bmp';

var tileSize = 30;
var maxTilesOnX = $("#WorldMap").width() / tileSize;
var maxTilesOnY = $("#WorldMap").height() / tileSize;

var offsetX = 0;
var offsetY = 0;

function draw() {

    $("#WorldMap").html(""); // clear map div

    context.drawImage(imageObj, 0, 0);

    for (var y = 0 + offsetY; y < maxTilesOnY + offsetY; y++) {
        for (var x = 0 + offsetX; x < maxTilesOnX + offsetX; x++) {

            var pixel = context.getImageData(x, y, 1, 1);
            // alert("x: " + x + " y: " + y + " " + pixel.data[0] + "," + pixel.data[1] + "," + pixel.data[2]);

            if ((pixel.data[0] == 0) && (pixel.data[1] == 255) && (pixel.data[2] == 0)) {
                $("#WorldMap").append("<div class = 'grass'></div>");
            }
            else if ((pixel.data[0] == 0) && (pixel.data[1] == 0) && (pixel.data[2] == 255)) {
                $("#WorldMap").append("<div class = 'ocean'></div>");
            }
            else if ((pixel.data[0] == 0) && (pixel.data[1] == 0) && (pixel.data[2] == 0)) {
                $("#WorldMap").append("<div class = 'null'></div>");
            }
        }

    }



    $(".grass").mouseenter(function () {
        $("#WorldMapMessage").html("grass");
    });
    $(".ocean").mouseenter(function () {
        $("#WorldMapMessage").html("ocean");
    });
    $(".null").mouseenter(function () {
        $("#WorldMapMessage").html("empty");
    });
}

imageObj.onload = draw();

// allows player to draw new portions of the map by using arrow keys
clickhandler = document.addEventListener('keydown', function (event) {
    if (event.keyCode == 37) { offsetX -= 5; draw();}
    else if (event.keyCode == 38) { offsetY += 5; draw(); } // up
    else if (event.keyCode == 39) { offsetX += 5; draw(); }
    else if (event.keyCode == 40) { offsetY -= 5; draw(); }
});

然而,一个按键需要浏览器大约 2.5 秒来处理和绘制所有这些数据,而且我有一个相当强大的处理器,这意味着对于普通用户来说它可能会非常缓慢。

如何提高算法速度?理想情况下,我希望滚动是实时的,以便玩家可以拖动地图,谷歌地图风格。我有几个想法:

  1. 通过 jquery 为每个图块定义左侧和顶部位置,而不是将它们全部加载并依靠相对定位使它们对齐。
  2. 将图块合并到画布中的单个图像中。但是,我确实需要维护光标悬停信息,以便玩家可以查询地形信息(以及稍后从服务器提取数据后将在顶部绘制的军队/城市。)
  3. 预加载整个地图。不理想,因为地图将是大约 100 万平方瓦片......
  4. 考虑使用 Flash 插件,但也不理想,因为我想尽量减少外部性能要求。

你们有没有人对我如何改进我的算法有建议,或者对要考虑的全新想法有什么建议?

谢谢!

4

1 回答 1

0

我不是专家,但缓存 DOM 元素是我要做的第一件事。 var $WorldMap = $("#WorldMap")

我不确定 .append() 方法有多快。这是一个很酷的站点,用于测试不同的 JS 方法。 jsperf.com

或者像这样打印地图:
0000111100000
0001111002220
0011100112201

然后简单地用你的元素替换它。

于 2013-07-06T08:52:24.483 回答