You need to enable JavaScript to run this app. 纯JavaScript开发2D平台射击游戏Tilemap渲染不全的解决方法
优惠活动
大模型
产品
解决方案
定价
更多

纯JavaScript开发2D平台射击游戏Tilemap渲染不全的解决方法

Tilemap渲染异常修复指南

目标效果与实际效果对比

第一关Tiled配置的目标效果
代码实际运行得到的地图效果

代码存在的核心问题

  • 索引计算逻辑错误:遍历瓦片数组时使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.11.05 20:27:03