p5.js访问history数组vector时同时显示数值与undefined报错是何原因
报错原因
- 数组下标越界:你在
show方法的for循环中,每次需要访问从i到i+6共7个数组元素,但循环终止条件写的是i < this.history.length,当i大于this.history.length - 7时,i+6已经超出了数组的下标范围,取到的值为undefined,访问undefined的x属性就会触发该报错。这也是你控制台同时打印出正常向量和undefined的原因:循环前半段i较小的时候访问正常,i接近数组长度时就会访问到不存在的元素。 - 循环逻辑错误:你每次在
update方法中向history数组一次性推入7个向量,对应一帧小鸟的完整顶点数据,循环步长应该设为7,否则会把不同帧的顶点混合拼接,得到错误的轨迹形状。 - 历史数据裁剪逻辑错误:当前逻辑中
history长度超过700时每次仅删除1个元素,会破坏7个元素为一组的顶点结构,应该每次删除7个元素保证剩余数据都是完整的帧数据。 - 渲染顺序错误:
draw函数中先执行show再执行update,第一帧运行时history为空,不会渲染历史轨迹,调整为先更新再渲染更合理。
修正后代码
class Bird { constructor(x0, y0, x1, y1, x2, y2, x3, y3, x4, y4, x5, y5, xend, yend) { this.x0 = x0; this.y0 = y0; this.x1 = x1; this.y1 = y1; this.x2 = x2; this.y2 = y2; this.x3 = x3; this.y3 = y3; this.x4 = x4; this.y4 = y4; this.x5 = x5; this.y5 = y5; this.xend = xend; this.yend = yend; this.history = []; this.t = 0; } update() { let r = noise(this.t + 5.2); let r2 = noise(this.t + 5.19); let r3 = noise(5 + this.t); let r5 = noise(5 + this.t); this.x0 = this.x0 + r; this.y0 = this.y0 + r; this.x1 = this.x1 + r2; this.y1 = this.y1 + r2; this.x2 = this.x2 + r3; this.y2 = this.y2 + r3; this.x3 = this.x3 + r; this.y3 = this.y3 + r; this.x4 = this.x4 + r5; this.y4 = this.y4 + r5; this.x5 = this.x5 + r; this.y5 = this.y5 + r; this.xend = this.xend + r; this.yend = this.yend + r; this.t += 0.005; let v0 = createVector(this.x0, this.y0); let v1 = createVector(this.x1, this.y1); let v2 = createVector(this.x2, this.y2); let v3 = createVector(this.x3, this.y3); let v4 = createVector(this.x4, this.y4); let v5 = createVector(this.x5, this.y5); let vend = createVector(this.xend, this.yend); this.history.push(v0, v1, v2, v3, v4, v5, vend); // 每次删除一组7个顶点,保证数据结构完整 if (this.history.length > 700) { this.history.splice(0, 7); } } show() { strokeWeight(1); stroke(255); noFill(); // 循环步长改为7,终止条件保证不会越界 for (let i = 0; i <= this.history.length - 7; i += 7) { let pos0 = this.history[i]; let pos1 = this.history[i + 1]; let pos2 = this.history[i + 2]; let pos3 = this.history[i + 3]; let pos4 = this.history[i + 4]; let pos5 = this.history[i + 5]; let posend = this.history[i + 6]; beginShape(); curveVertex(pos0.x, pos0.y); curveVertex(pos1.x, pos1.y); curveVertex(pos2.x, pos2.y); curveVertex(pos3.x, pos3.y); curveVertex(pos4.x, pos4.y); curveVertex(pos5.x, pos5.y); curveVertex(posend.x, posend.y); endShape(); } // 渲染当前帧小鸟 beginShape(); curveVertex(this.x0, this.y0); curveVertex(this.x1, this.y1); curveVertex(this.x2, this.y2); curveVertex(this.x3, this.y3); curveVertex(this.x4, this.y4); curveVertex(this.x5, this.y5); curveVertex(this.xend, this.yend); endShape(); } } let bird; function setup() { createCanvas(displayWidth, displayHeight); bird = new Bird(800, 560, 700, 350, 600, 250, 700, 300, 790, 240, 700, 350, 450, 500); } function draw() { background(70); // 先更新再渲染,避免第一帧无历史数据 bird.update(); bird.show(); }
内容的提问来源于stack exchange,提问作者SwanPrince
相关产品推荐
相关产品推荐

