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

Canvas中fillRect不显示:滑雪游戏树木绘制问题求助

问题分析与修复

你的树木无法显示的核心问题出在tree()函数里的**treeY未初始化**,导致它的值始终是undefined,后续计算会得到NaN,fillRect接收无效的Y坐标后自然画不出任何东西。除此之外,代码还有几个逻辑问题需要调整,才能让树木正常生成并移动:

具体问题点

  • treeY未初始化:第一次调用tree()时,treeY没有赋值,undefined < 1的结果为false,进入else分支后treeY -= speed会得到NaN,这是无效的坐标值
  • 每一帧都生成新树:update()里每次都调用tree(),会导致每一帧都创建新树,很快画布会被填满
  • treeX随机范围错误:Math.floor(Math.random() * (canvas.width + 1)) + 25会让树木X坐标超出画布宽度,导致树木显示在画布外

修复后的代码

var canvas = document.getElementById("canvas"),
  ctx = canvas.getContext("2d");

canvas.width = 1000;
canvas.height = 800;

var x = canvas.width / 2,
  speed = 3, // 调大速度让移动更明显
  size = 5,
  alive = 1,
  keys = [],
  trees = []; // 用数组存储所有树木

function player() {
  if (alive === 1) {
    if (keys[37] || keys[65]) {
      x -= 3;
    }
    if (keys[39] || keys[68]) {
      x += 3;
    }

    x = Math.max(0, Math.min(canvas.width, x)); // 简化边界判断

    ctx.beginPath();
    ctx.fillStyle = "black";
    ctx.arc(x, 100, size, 0, Math.PI * 2);
    ctx.fill();
  }
}

// 生成新树的函数
function spawnTree() {
  // 控制X坐标在画布内,留出树木宽度的余量
  var treeX = Math.floor(Math.random() * (canvas.width - 5));
  // 从画布底部外开始生成
  trees.push({x: treeX, y: canvas.height + 8});
}

// 更新并绘制所有树木
function updateTrees() {
  ctx.fillStyle = "green";
  // 倒序遍历,避免删除元素时索引混乱
  for (let i = trees.length - 1; i >= 0; i--) {
    let tree = trees[i];
    tree.y -= speed;
    
    // 绘制树木
    ctx.fillRect(tree.x, tree.y, 5, 8);
    
    // 移除超出画布顶部的树木
    if (tree.y < -8) {
      trees.splice(i, 1);
    }
  }
}

function update() {
  requestAnimationFrame(update);
  ctx.clearRect(0, 0, canvas.width, canvas.height);

  player();
  updateTrees();
  
  // 控制树木生成频率,比如每60帧左右生成一棵
  if (Math.random() < 0.015) {
    spawnTree();
  }
}

update();

document.body.addEventListener("keydown", function(e) {
  keys[e.keyCode] = true;
});
document.body.addEventListener("keyup", function(e) {
  keys[e.keyCode] = false;
});
<canvas id="canvas"></canvas>

关键修改说明

  1. 新增树木数组:用trees数组存储所有树木的坐标,方便统一管理和更新
  2. 拆分树木逻辑:把生成树木和更新绘制树木拆成两个函数,逻辑更清晰
  3. 初始化treeY:新生成的树木从画布底部外开始,保证一开始就能进入画布
  4. 调整随机范围:treeX的最大值设为canvas.width - 5,避免树木超出画布右侧
  5. 控制生成频率:用Math.random() < 0.015控制每帧生成树木的概率,避免树木过多
  6. 移除过期树木:当树木超出画布顶部时,从数组中移除,避免不必要的内存占用

这样修改后,绿色的树木就会从画布底部向上移动,你可以根据需求调整speed和生成频率参数,让游戏体验更符合预期。

内容的提问来源于stack exchange,提问作者Only-Spiders-Like-Bugs

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 10:25:22