AbrarShahriar
AbrarShahriar

Reputation: 163

Multiple object intersection and removal problem [ processing/p5.js ]

I am new to stack and not quite sure how to use it. But here I am. I am working on a ecosystem project, and I have an animal class with 2 different genders(0 for female, 1 for male). When 2 different genders intersect each other than I want to remove those 2 objects and add a couple(different object, static) object on that position. I kinda did it but it only works for a couple of seconds. Then the code just breaks. In the console it says, “Uncaught TypeError: Cannot read property ‘intersects’ of undefined”

Here's the question on the processing forum in case I get a solution which might help others: https://discourse.processing.org/t/multiple-object-intersection-and-removal/22900/2

Here's the sketch.js file:

var animats = [];

var couples = [];

function setup() {
frameRate(30);
             
createCanvas(displayWidth, 470);
            
for(var i = 0; i < 50; i++) 
{
animats[i] = new Animat(random(0, width), random(0, height));

}

}

function draw() {

background(255,100,100);
        
for(var i = animats.length-1; i >= 0; i--) {    
             
animats[i].birth(); 
                
animats[i].grow();

 for(var j = i; j >= 0; j--) {
                                      
   if(j != i && animats[i].intersects(animats[j])) {
                                                        
   animats.splice(i, 1);
                                                              
   animats.splice(j, 1);
                            
                                                     
 }
                             
 }
 }  

 }

Here's the animat class file:

function Animat(x, y) {
            this.x = x;
            this.y = y;
            
            this.gender;
            var g = random(0,1);
            var c;
                            
                            if(g > 0.5) {
                                            c = 0;
                                this.gender = 0;
                            } else {
                                            c = 255;
                                this.gender = 1;
                            }
            
            this.speed = 1;

            this.age = 0;
            this.length = 0.5;
            
            this.birth = function() {
                            
                            //gender
                            
                            //create
                            noStroke();
                            fill(c);
                            text("n", this.x, this.y, this.length, this.length);
                            ellipse(this.x, this.y, this.length * 2, this.length * 2);
                            
                            
                            //move
                            
                            switch(floor(random(0,4))) {
                                            case 0:
                                                            this.x += this.speed;
                      break;
                                            case 1:
                                                            this.y += this.speed;
                      break;
                                            case 2:
                                                            this.x -= this.speed;
                      break;
                                            case 3:
                                                            this.y -= this.speed;
                      break;
                                            default:
                                                            this.x++;
                                                            this.y--;
                            }
                            
                //bounce
                            
                            if(this.x > width || this.x < 4){
                                            this.speed *= -1;
                            }
                            if(this.y > height || this.y < 4){
                                            this.speed *= -1;
                            }
                                            
            }

            this.grow = function() {
                            this.age += 0.01;
                            this.length += 0.05;
                            
                            //age checks
                            
                            if(this.age > 10) {
                                            this.speed + 5;
                            } else if(this.age > 21) {
                                            this.length = 25;
                                            this.speed = this.speed
                                            //console.log("max age:" + this.age)
                            } else if(this.age > 70) {
                                            //die
                            } else {
                                            
                            }
                            
                            //length checks 
                            
                            if(this.length > 25) {
                                            this.length = 25;
                                         //console.log("max length");
                            }
            }
            
            //relationship
            
            this.intersects = function(other) {
                            var d = dist(this.x, this.y, other.x, other.y);
                            var r = this.length + other.length;
                            
                            if(d < r) {
                                            if(((this.gender == 0) && (other.gender == 1)) || ((this.gender == 1) && (other.gender == 0))) {
                                                return true;
                                            } else {
                                                            this.speed *= -1;
                                            }
                                            
                            } else {
                                            return false;
                            }
            }
            
            //mate
            
         this.couple = function() {
                            if(((this.gender == 0) && (other.gender == 1)) || ((this.gender == 1) && (other.gender == 0))) {
                                                return true;
                                            } else {
                                                            this.speed *= -1;
                                            }
            }
            
            //die
            
         /*this.die = function() {
                    if(this.age > 50) {
                                            return true;
                            } else {
                                            return false;
                            }
   }*/
            

}

Here's the codepen link for results I am getting: https://codepen.io/AbrarShahriar/pen/XWXwLPM

Upvotes: 1

Views: 255

Answers (2)

Chen Ni
Chen Ni

Reputation: 1144

Try changing your nested for loop to:

for (var i = animats.length - 1; i >= 0; i--) {
  animats[i].birth();
  animats[i].grow();
  for (var j = i; j >= 0; j--) {
    if (j != i && animats[i].intersects(animats[j])) {
      animats.splice(i, 1);
      animats.splice(j, 1);
      break; //exit the inner loop after a match
    }
  }
}

In other words, add a break; after two animats have coupled and have been removed from the array. The error was probably caused by you trying to call the intersects method of an animat that had already been removed.

Upvotes: 2

SirPilan
SirPilan

Reputation: 4847

you need to keep animats[i] as long as the for-loop for j has not finished.

Here the code you need to fix:

for(var i = animats.length-1; i >= 0; i--) {
    animats[i].birth();
    animats[i].grow();
    let remove = false; // mark 'i' as NOT REMOVE by default
                            
    for(var j = i; j >= 0; j--) {
        if(j != i && animats[i].intersects(animats[j])) {
            remove = true; // mark 'i' as to remove when collision detected
            animats.splice(j, 1);
        }
    }

    if (remove) { // remove 'i' after compared to all 'j'
        animats.splice(i, 1);
    }
}

Upvotes: 1

Related Questions