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
相关产品推荐
相关产品推荐

