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

使用Canvas实现T-rex恐龙游戏无限滚动地面的技术问题

问题核心原因

  1. createPattern返回的是CanvasPattern填充对象,不是Image实例,不能直接传入drawImage作为第一个参数,这是你标记/////2的写法报错的直接原因。
  2. 你原来的createPattern方案(/////1)之所以没生效,是因为pattern默认从画布左上角(0,0)开始平铺,仅移动fillRect的x坐标不会改变pattern的填充位置,视觉上就不会产生移动效果。
  3. 地面移动方向错误:默认gameSpeed为正值的话,地面会向右移动,不符合恐龙向前跑地面向后退的视觉逻辑。
  4. 无限滚动逻辑缺失:即便给地面设置20000的超大宽度,最终还是会移出画布,无法做到真正的无限循环。

推荐实现方案(双图拼接法,兼容性好逻辑简单)

这是同类跑酷游戏最常用的实现方案,不需要复杂的API,靠两张连续的地面图循环拼接实现无缝滚动:

// 单独封装地面类,和通用障碍物类逻辑区分开
class Terrain {
  constructor(image, y) {
    this.image = image;
    this.y = y;
    this.imgWidth = image.width; // 单张地面素材的宽度
    this.xOffset = 0; // 横向滚动偏移量
    this.speed = -gameSpeed; // 地面向左移动,速度取负值
  }

  animate() {
    this.xOffset += this.speed;
    // 偏移量超过单张地面宽度时重置,实现无缝循环
    if (Math.abs(this.xOffset) >= this.imgWidth) {
      this.xOffset = 0;
    }
    this.draw();
  }

  draw() {
    // 绘制第一张地面
    ctx.drawImage(this.image, this.xOffset, this.y);
    // 紧接第一张的右侧绘制第二张,保证视觉连续
    ctx.drawImage(this.image, this.xOffset + this.imgWidth, this.y);
  }
}

// 初始化部分修改为
function start() {
  // ...其他逻辑
  terrain = new Terrain(landImage, canvas.height - 20);
  update();
}

如果你想沿用createPattern的实现思路

需要通过修改画布的变换矩阵来移动pattern的填充位置,修改draw方法如下:

draw() {
  // 每次绘制前保存画布状态,避免影响其他元素
  ctx.save();
  // 移动pattern的填充偏移
  ctx.translate(this.xOffset, this.y);
  const pat = ctx.createPattern(this.image, 'repeat-x');
  ctx.fillStyle = pat;
  // 填充范围覆盖整个画布宽度即可,不需要设置超大宽度
  ctx.fillRect(-this.xOffset, 0, canvas.width, 20);
  // 恢复画布状态
  ctx.restore();
}

注意这种方案需要每次更新偏移量后重设变换,性能略低于双图拼接法。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 02:51:00