我正在尝试创建一个程序,当画布左边缘生成的粒子到达画布右端时,它们会从数组中移除(使用拼接)。
let P = [];
let n = 10;
function setup()
{
createCanvas(500,500);
for(let i = 0; i < n; i++)
P.push(new particle());
}
function draw()
{
background(0);
for(let i = 0; i < n; i++)
{
if(P[i].out == true)
{
P.splice(i, 1);
n--;
}
P[i].update();
P[i].plot();
console.log(P.length)
}
}
class particle
{
constructor()
{
this.brightness = 0;
this.vel = random(1);
this.dia = 3;
this.x = 0;
this.y = random(height);
this.out = false;
}
update()
{
this.x += this.vel;
if(this.x >= width)
this.out = true;
}
plot()
{
noStroke();
fill(255);
circle(this.x, this.y, this.dia);
}
}
程序运行时,大部分似乎都能正常工作。为了确保数组中的元素确实被删除,我试着记录数组的长度。当我运行它时,元素在到达画布的右端时被删除,但当数组的大小减少到大约30%左右时(每次运行都不同),我得到了这个错误。
Uncaught TypeError: 无法读取未定义的属性'update'。
我被这个问题难住了,因为我不明白为什么之前在循环中已经使用了好几次的update函数却无法被读取。
问题是,当你在数组中迭代时,你会从数组中移除元素。注意:在数组中迭代的同时,从数组中删除元素。P.splice(i, 1);
从数组中删除一个元素,如果该元素是数组中的最后一个元素,那么 P[i].update();
访问数组越界。这将导致错误 "Uncaught TypeError.Cannot read property 'update' of undefined 无法读取未定义的'update'属性"
我建议从后面遍历数组:(参见 在数组中循环并删除项目,不需要中断循环。)
let i = P.length;
while (i--) {
if (P[i].out == true) {
P.splice(i, 1);
n--;
} else {
P[i].update();
P[i].plot();
}
}
请看这个例子。
let P = [];
let n = 10;
function setup()
{
createCanvas(500,500);
for(let i = 0; i < n; i++)
P.push(new particle());
}
function draw()
{
background(0);
let i = P.length;
while (i--) {
if (P[i].out == true) {
P.splice(i, 1);
} else {
P[i].update();
P[i].plot();
}
}
}
class particle
{
constructor()
{
this.brightness = 0;
this.vel = random(1);
this.dia = 3;
this.x = 0;
this.y = random(height);
this.out = false;
}
update()
{
this.x += this.vel;
if(this.x >= width)
this.out = true;
}
plot()
{
noStroke();
fill(255);
circle(this.x, this.y, this.dia);
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.0.0/p5.min.js"></script>
因为你要从数组中移除元素,你需要向后迭代它。
function draw() {
background(0);
for(let i = n - 1; i >= 0; i--) {
if(P[i].out == true) {
P.splice(i, 1);
n--;
}
P[i].update();
P[i].plot();
console.log(P.length)
}
}