Estoy tratando de crear un programa donde las partículas generadas en el borde izquierdo del lienzo se eliminen de la matriz (usando el empalme) cuando alcanzan el extremo derecho del lienzo.

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

El programa parece estar funcionando bien en su mayor parte cuando se ejecuta. Para asegurarme de que los elementos de la matriz se están eliminando, intenté registrar la longitud de la matriz. Cuando lo ejecuto, los elementos se eliminan cuando llegan al extremo derecho del lienzo, pero a medida que el tamaño de la matriz disminuye a aproximadamente el 30% (es diferente cada vez que lo ejecuto), aparece este error:

TypeError no capturado: no se puede leer la propiedad 'actualización' de undefined

Estoy perplejo por esto porque no entiendo cómo la función de actualización no se puede leer cuando ya se ha usado varias veces en el ciclo anteriormente.

1
Rumble down 28 abr. 2020 a las 15:02

2 respuestas

La mejor respuesta

El problema es que elimina elementos de la matriz, mientras itera a través de la matriz. Nota P.splice(i, 1); elimina un elemento de la matriz si ese fue el último elemento en la matriz, luego P[i].update(); accede a la matriz fuera de los límites. Eso provoca el error "Error de tipo no capturado: no se puede leer la propiedad 'actualización' de indefinido"

Recomiendo atravesar la matriz desde atrás:
(Consulte también Recorriendo la matriz y eliminando elementos, sin romper para bucle)

let i = P.length;
while (i--) {
    if (P[i].out == true) {
        P.splice(i, 1);
        n--;
    } else {
        P[i].update();     
        P[i].plot();
    }
}

Mira el ejemplo:

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>
2
Rabbid76 28 abr. 2020 a las 12:53

Dado que está eliminando elementos de la matriz, debe iterar hacia atrás:

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)
    }   
}
1
Schred 28 abr. 2020 a las 12:47