纯JavaScript开发2D平台射击游戏Tilemap渲染不全的解决方法
Tilemap渲染异常修复指南
目标效果与实际效果对比


代码存在的核心问题
- 索引计算逻辑错误:遍历瓦片数组时使用
map[((y*rows)+x)]获取瓦片编号,数组每行长度为cols=25,正确的行偏移量应该用cols计算,写成rows=18会导致每一行的索引跳转错位,瓦片位置完全混乱。 - 资源加载时序错误:
Image对象的加载是异步过程,window.onload触发时无法保证所有瓦片图片已经下载完成,此时执行绘制会输出空白内容。 - 语法错误:
drawMap函数缺少闭合大括号,会直接触发JS语法报错,导致函数无法正常执行。
修复后的完整代码
window.onload = function () { var canvas = document.getElementById("canvas"); var ctx = canvas.getContext('2d'); var cols = 25; var rows = 18; var tileWidth = 32; var tileHeight = 32; canvas.width = cols * tileWidth; canvas.height = rows * tileHeight; var map = [ 467,468,468,468,468,468,468,467,468,468,468,468,468,468,468,468,467,468,468,468,468,468,467,468,468, 499,500,501,468,468,468,468,499,500,501,468,468,468,468,468,468,499,500,501,468,468,468,499,500,501, 468,468,468,468,468,467,468,468,468,468,468,499,500,501,468,468,468,468,468,467,468,468,468,468,468, 468,468,468,468,468,499,500,501,468,468,468,468,468,468,468,468,468,468,468,499,500,501,468,468,468, 468,467,468,468,468,468,468,468,468,467,468,468,468,468,467,468,468,468,468,468,468,468,467,468,468, 468,499,500,501,468,468,468,468,468,499,500,501,468,468,499,500,501,468,468,468,468,468,499,500,501, 468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468, 468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468, 468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468, 468,468,468,468,468,468,468,468,282,282,282,282,282,282,282,282,282,468,468,468,468,468,468,468,468, 468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468, 468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468, 468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468, 468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468, 258,258,258,258,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,258,258,258,258, 528,528,528,528,258,258,258,258,258,258,258,258,258,258,258,258,258,258,258,258,258,528,528,528,528, 528,528,528,528,528,528,528,528,528,528,528,528,528,528,528,528,528,528,528,528,528,528,528,528,528, 528,528,528,528,528,528,528,528,528,528,528,528,528,528,528,528,528,528,528,528,528,528,528,528,528 ]; // 统一管理瓦片图片与加载状态 const tileImageMap = {}; const tileTypes = [467, 468, 499, 500, 501, 528, 258, 282]; let loadedImageCount = 0; function onAllTileLoaded() { loadedImageCount++; // 所有瓦片加载完成后执行绘制 if (loadedImageCount === tileTypes.length) { drawMap(); // 在此处启动原有的animate函数即可 } } // 初始化所有瓦片资源 tileTypes.forEach(type => { const img = new Image(); img.src = `${type}_tile.png`; img.onload = onAllTileLoaded; tileImageMap[type] = img; }); function drawMap() { for (var y = 0; y < rows; y++){ for (var x = 0; x < cols; x++) { // 修正索引计算逻辑 const currentTileType = map[y * cols + x]; const tileImg = tileImageMap[currentTileType]; if (tileImg) { ctx.drawImage(tileImg, x * tileWidth, y * tileHeight, tileWidth, tileHeight); } } } } }
优化建议
- 可以用对象映射替换原有
switch判断逻辑,减少冗余代码,后续新增瓦片类型时不需要修改绘制循环 - 后续接入Tiled编辑器导出的JSON格式地图时,可直接读取文件内的宽高、瓦片数组字段,无需手动硬编码map数组
内容的提问来源于stack exchange,提问作者synco
相关产品推荐
相关产品推荐

