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

Canvas考试项目:道路标线批量生成与视野外销毁问题咨询

Canvas车辆游戏道路标线实现方案

问题解答

1. 持续生成多个道路标线

可以通过帧计数定时生成的方式实现持续生成,而非一次性用for循环批量创建。利用frameCount判断间隔帧数,每达到指定帧数就往数组中添加一组新标线,这样能模拟出自然的持续生成效果。

2. 删除视野外的标线

使用数组管理所有标线是正确的方案。每次绘制时,检查标线是否超出画布底部(完全离开视野),将这类标线从数组中移除,就能避免无效对象占用内存导致卡顿。


修改后的完整代码

let crashcar;
let carsonroad;

let roadLinesArray = [];
// 控制生成标线的间隔帧数
const LINE_SPAWN_INTERVAL = 30;
// 数组最大容量,避免过多对象
const MAX_LINES = 20;

function setup() {
  createCanvas(720, 540);
  rectMode(CENTER);
  crashcar = new Crashcar();
  carsonroad = new CarsOnRoad();
  // 初始化时先添加几组错落的标线,避免初始空白
  for(let i = 0; i < 5; i++) {
    roadLinesArray.push(new RoadLine(i * 40));
  }
}

function draw() {
  background('#1ebc09ff');
  drawRoad();
  drawRoadLines();
  drawRoadBorders();
  crashcar.display();
  carsonroad.display();
  moveCar();

  // 定时生成新标线,同时限制数组长度不超过最大值
  if(frameCount % LINE_SPAWN_INTERVAL === 0 && roadLinesArray.length < MAX_LINES) {
    roadLinesArray.push(new RoadLine());
  }
}

function drawRoad() {
  fill(100);
  noStroke();
  rect(width / 2, height / 2, width - 280, height);
}

function drawRoadLines() {
  // 遍历数组渲染所有标线,同时过滤掉视野外的无效标线
  roadLinesArray = roadLinesArray.filter(line => {
    line.update();
    line.display();
    // 标线完全超出画布底部后移除
    return line.pos1.y < height + 20;
  });
}

function drawRoadBorders() {
  fill(255);
  noStroke();
  rect(140, height / 2, 10, height);
  rect(width - 140, height / 2, 10, height);
}

function moveCar() {
  if (keyIsDown(68) || keyIsDown(RIGHT_ARROW)) {
    crashcar.moveRight();
  }
  if (keyIsDown(65) || keyIsDown(LEFT_ARROW)) {
    crashcar.moveLeft();
  }
}

class Crashcar {
  constructor() {
    this.pos = createVector(width / 2, height / 2)
  }

  display() {
    fill('#ff0000ff');
    rect(this.pos.x, this.pos.y, 30, 40);
  }

  moveRight() {
    let VelRight = createVector(5, 0);
    this.pos.add(VelRight);

    if (this.pos.x > width - 155) {
      this.pos.x = width - 155;
    }
  }

  moveLeft() {
    let VelLeft = createVector(-5, 0);
    this.pos.add(VelLeft);

    if (this.pos.x < 155) {
      this.pos.x = 155;
    }
  }
}

class CarsOnRoad {
  constructor() {
    this.x = width / 2;
    this.y = 0 + 20;
  }

  display() {
    fill('#ffe600ff');
    rect(this.x, this.y, 30, 40);
  }
}

class RoadLine {
  constructor(initialY = 0) {
    this.pos1 = createVector(width / 3 + 200, initialY);
    this.pos2 = createVector(width / 3 + 40, initialY);
    this.vel = createVector(0, 5);
  }

  // 拆分移动逻辑到单独方法,职责更清晰
  update() {
    this.pos1.add(this.vel);
    this.pos2.add(this.vel);
  }

  display() {
    fill(255);
    noStroke();
    rect(this.pos1.x, this.pos1.y, 6, 20);
    rect(this.pos2.x, this.pos2.y, 6, 20);
  }
}

class Obstacle {
  constructor() {

  }
}

关键改动说明

  • 重构RoadLine类:将移动逻辑拆分为update()方法,同时支持传入初始y坐标,方便初始化时生成错落的标线
  • 标线生成逻辑:在draw()中通过frameCount % LINE_SPAWN_INTERVAL === 0控制每30帧生成一组新标线,同时限制数组长度不超过MAX_LINES
  • 视野外标线移除:在drawRoadLines()中使用filter()方法,自动移除完全超出视野的标线,避免内存浪费
  • 初始化填充:在setup()中先生成5组错落的标线,避免游戏开始时道路空白

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.11 18:05:11