我正在开发一个基于浏览器的网页游戏,其中包含一个非常大的 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 秒来处理和绘制所有这些数据,而且我有一个相当强大的处理器,这意味着对于普通用户来说它可能会非常缓慢。
如何提高算法速度?理想情况下,我希望滚动是实时的,以便玩家可以拖动地图,谷歌地图风格。我有几个想法:
- 通过 jquery 为每个图块定义左侧和顶部位置,而不是将它们全部加载并依靠相对定位使它们对齐。
- 将图块合并到画布中的单个图像中。但是,我确实需要维护光标悬停信息,以便玩家可以查询地形信息(以及稍后从服务器提取数据后将在顶部绘制的军队/城市。)
- 预加载整个地图。不理想,因为地图将是大约 100 万平方瓦片......
- 考虑使用 Flash 插件,但也不理想,因为我想尽量减少外部性能要求。
你们有没有人对我如何改进我的算法有建议,或者对要考虑的全新想法有什么建议?
谢谢!