You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Canvas中DrawImage在循环内无法绘制的问题求助

解决Canvas无法绘制地图边框的问题

嘿,作为刚接触游戏编程和JavaScript的新手,遇到这种Canvas不渲染的问题太正常了,我帮你拆解下代码里的几个关键问题,改完应该就能正常显示了:

1. 图片加载的异步问题是核心

你的textures.onload回调写法不对,而且现在的代码是图片还没加载完成就调用了drawDungeon,这时候drawImage根本无法正常绘制图片。另外,onload的回调参数不是x,y,而是一个事件对象。

正确的做法是把所有依赖图片的绘制逻辑放到onload回调里,确保图片加载完成后再执行:

textures.onload = function() {
  createDungeon(6400, 4800);
  drawDungeon(Camera.posX, Camera.posY, canvas.width, canvas.height);
}
textures.src = "Images/textures.jpg";

2. 未声明的全局变量会破坏循环逻辑

你代码里的a、b、c都没有用let/var/const声明,会变成全局变量,导致嵌套循环的计数逻辑混乱——比如内层循环的a会覆盖外层的a,直接让循环跑错。

给所有循环变量加上let声明,示例:

for(let a=0; a<height; a+=32) {
  for(let b=0; b<width; b+=32) {
    // ...
  }
}

3. drawImage的参数不完整

你现在调用ctx.drawImage(textures, b, a)只传了3个参数,这表示把整张图片从(b,a)的位置开始绘制,但你需要的是从tileset里裁剪出单个32x32的tile来画。假设你的tileset里第一个边框tile在左上角(0,0)位置,正确的drawImage写法应该是:

ctx.drawImage(textures, 0, 0, 32, 32, b, a, 32, 32);

参数依次是:源图片、源裁剪x坐标、源裁剪y坐标、源裁剪宽度、源裁剪高度、目标x坐标、目标y坐标、目标宽度、目标高度。

4. 优化drawDungeon的遍历逻辑(可选但重要)

你现在每次绘制一个tile都要遍历整个dungeon数组找匹配项,这对于6400x4800的大地图来说效率极低,完全没必要。其实可以通过坐标直接计算出对应的tile类型,不用存dungeon数组:

function drawDungeon(startX, startY, width, height) {
  for(let a=0; a<height; a+=32) {
    for(let b=0; b<width; b+=32) {
      // 计算当前tile的全局坐标
      const globalX = b + startX;
      const globalY = a + startY;
      // 判断是不是地图边框
      if(globalX === 0 || globalX === 6400 - 32 || globalY === 0 || globalY === 4800 - 32) {
        // 绘制边框tile
        ctx.drawImage(textures, 0, 0, 32, 32, b, a, 32, 32);
      } else {
        // 绘制白色地面
        ctx.fillStyle = "#ffffff";
        ctx.fillRect(b, a, 32, 32);
      }
    }
  }
}

这样直接去掉dungeon数组,代码更简洁,运行效率也高很多。

修改后的完整代码

var canvas = document.getElementById("gameCanvas");
var ctx = canvas.getContext("2d");
canvas.width = 640;
canvas.height = 480;

var Camera = {
  posX: 0,
  posY: 0,
}

var textures = new Image();
textures.onload = function() {
  drawDungeon(Camera.posX, Camera.posY, canvas.width, canvas.height);
}
textures.src = "Images/textures.jpg";

// 直接通过坐标判断边框,无需dungeon数组
function drawDungeon(startX, startY, width, height) {
  for(let a=0; a<height; a+=32) {
    for(let b=0; b<width; b+=32) {
      const globalX = b + startX;
      const globalY = a + startY;
      // 判断是否为地图边框
      if(globalX === 0 || globalX === 6400 - 32 || globalY === 0 || globalY === 4800 - 32) {
        ctx.drawImage(textures, 0, 0, 32, 32, b, a, 32, 32);
      } else {
        ctx.fillStyle = "#ffffff";
        ctx.fillRect(b, a, 32, 32);
      }
    }
  }
}

这样改完之后,Canvas应该就能正常显示带边框的地图了。如果还有问题,可以检查下textures.jpg的路径是否正确,确保图片能正常加载~

内容的提问来源于stack exchange,提问作者Ben Klayer

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:24:38