开发者问题收集

多对象相交及移除问题 [ processing/p5.js ]

2020-07-29
242

我是 Stack 的新手,不太清楚如何使用它。但我还是来了。我正在做一个生态系统项目,我有一个动物类,它有两种不同的性别(0 代表雌性,1 代表雄性)。当两种不同的性别相互交叉时,我想移除这两个对象,并在该位置添加一对(不同的对象,静态)对象。我有点做到了,但它只起作用了几秒钟。然后代码就中断了。控制台显示,“未捕获的 TypeError:无法读取未定义的属性‘intersects’”

以下是处理论坛上的问题,以防我得到可能对其他人有帮助的解决方案: https://discourse.processing.org/t/multiple-object-intersection-and-removal/22900/2

以下是 sketch.js 文件:

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

 }

以下是 animat 类文件:

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;
                            }
   }*/

>

以下是我得到的结果的 codepen 链接: https://codepen.io/AbrarShahriar/pen/XWXwLPM

2个回答

尝试将嵌套的 for 循环更改为:

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

换句话说,在两个 animats 耦合并从数组中移除后添加 break; 。错误可能是由于您尝试调用已被移除的 animatintersects 方法造成的。

Chen Ni
2020-07-30

只要 j 的 for 循环尚未完成,您就需要保留 animats[i]

这是您需要修复的代码:

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);
    }
}
SirPilan
2020-07-30