p5.js - 无法在程序运行时的随机点读取我的更新函数

p5.js - unable to read my update function at a random point in the program runtime

我正在尝试创建一个程序,其中在 canvas 左边缘生成的粒子在到达 canvas 右端时从阵列中移除(使用拼接)。

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);
    }  
}

该程序在 运行 时似乎大部分都运行良好。为了确保数组中的元素确实被删除,我尝试记录数组的长度。 当我 运行 它时,元素在到达 canvas 的右端时被删除,但是随着数组的大小减小到大约 30% 左右(每次我 运行 它),我得到这个错误:

Uncaught TypeError: Cannot read property 'update' of undefined

我被这个难住了,因为我不明白为什么更新函数在之前已经在循环中使用过几次时无法读取。

由于要从数组中删除元素,因此需要向后迭代它:

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)
    }   
}

问题是,您在遍历数组时从数组中删除了元素。注意 P.splice(i, 1); 从数组中删除一个元素,如果它是数组中的最后一个元素,然后 P[i].update(); 越界访问数组。这会导致错误 "Uncaught TypeError: Cannot read property 'update' of undefined"

我推荐从后面遍历数组:
(另请参阅 Looping through array and removing items, without breaking for loop

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>