p5.js实现寻路行为时出现"v1.copy"无法调用为函数错误求助
转向行为寻路代码错误排查与修复
我跟着Daniel Shiffman的转向行为(寻路)教程写代码,创建了Vehicle和Target两个类并加入主sketch,但出现错误:"v1.copy" could not be called as a function,错误还指向不存在的行。VS Code和Chrome里测试都是这个错,但Chrome指向的行不一样。预期功能是让Vehicle对象追踪Target对象。
原代码
主sketch代码
let vehicle; let target; function setup() { createCanvas(400, 400); vehicle = new Vehicle(50, 50); target = new Target(mouseX, mouseY); } function draw() { background(220); let steering = vehicle.seek(target); vehicle.applyForce(steering); vehicle.show(); vehicle.update(); target.show(); target.update(); }
Vehicle类代码
class Vehicle { constructor(x, y) { this.pos = createVector(x, y); this.vel = createVector(0, 0); this.acc = createVector(0, 0); this.maxSpeed = 4; this.maxForce = 1; this.r = 16; } seek(target) { let force = p5.Vector.sub(target, this.pos); force.setMag(this.maxSpeed); force.sub(this.vel); force.limit(this.maxForce); return force; } applyForce(force) { this.acc.add(force); } update() { this.vel.add(this.acc); this.vel.limit(this.maxSpeed); this.pos.add(this.vel); this.acc.set(0, 0); } show() { noStroke(); fill(0); push(); translate(this.pos.x, this.pos.y); rotate(this.vel.heading()); triangle(-this.r, -this.r / 2, -this.r, this.r / 2, this.r, 0); pop(); } } class Target extends Vehicle { constructor(x, y) { super(x, y); } show() { noStroke(); fill(200, 0, 0); ellipse(this.pos.x, this.pox.y, this.r); } }
错误原因与修复方案
1. 核心错误:seek方法参数类型不匹配
p5.Vector.sub()需要传入两个p5.Vector对象,但调用vehicle.seek(target)时传的是Target类实例,不是它的位置向量。这会导致p5内部尝试对非向量对象调用copy方法,触发"v1.copy" could not be called as a function错误。
修复:将let steering = vehicle.seek(target);改为let steering = vehicle.seek(target.pos);
2. 笔误拼写错误
Target类的show方法里,this.pox.y是拼写错误,应该是this.pos.y,否则会导致无法正确绘制目标点。
3. Target的update逻辑冗余
Target继承了Vehicle的update方法,但Target不需要速度、加速度的物理更新,应该重写update方法让它直接跟随鼠标位置。
修正后的完整代码
主sketch代码
let vehicle; let target; function setup() { createCanvas(400, 400); vehicle = new Vehicle(50, 50); target = new Target(mouseX, mouseY); } function draw() { background(220); // 传入Target的位置向量而非对象本身 let steering = vehicle.seek(target.pos); vehicle.applyForce(steering); vehicle.update(); vehicle.show(); target.update(); target.show(); }
Vehicle类代码
class Vehicle { constructor(x, y) { this.pos = createVector(x, y); this.vel = createVector(0, 0); this.acc = createVector(0, 0); this.maxSpeed = 4; this.maxForce = 1; this.r = 16; } seek(target) { let force = p5.Vector.sub(target, this.pos); force.setMag(this.maxSpeed); force.sub(this.vel); force.limit(this.maxForce); return force; } applyForce(force) { this.acc.add(force); } update() { this.vel.add(this.acc); this.vel.limit(this.maxSpeed); this.pos.add(this.vel); this.acc.set(0, 0); } show() { noStroke(); fill(0); push(); translate(this.pos.x, this.pos.y); rotate(this.vel.heading()); triangle(-this.r, -this.r / 2, -this.r, this.r / 2, this.r, 0); pop(); } } class Target extends Vehicle { constructor(x, y) { super(x, y); } // 重写update方法,让目标跟随鼠标 update() { this.pos.set(mouseX, mouseY); } show() { noStroke(); fill(200, 0, 0); // 修正拼写错误 ellipse(this.pos.x, this.pos.y, this.r); } }
内容的提问来源于stack exchange,提问作者Arsalan Aboomohsenpour
相关产品推荐
相关产品推荐

