Help a newbie with polymorphic particles

The main problem still persists: Your Ball calls has an ARRAY OF BALLS in it. So for every Ball in the gloab array, you are storing a copy of that array for each ball in it! Argh!

A Ball object represents ONE ball. There is no need to have an array of them inside your class!

Instead, you need to check pass a Ball to your collide() function. Then the collision is checking between the Ball you are calling collide on, and that other Ball, the one being passed in.

int numBalls = 4;
int numBlips = 15;

Ball[] balls = new Ball[numBalls+numBlips];

float spring = 1.6;
float gravity = 0.001;
float friction = -0.8;

void setup() {
  //frameRate(80); // Sketch will run as fast as it can anyway, usually 60fps. This doesn't increase that, much as you would like.

  size(displayWidth, displayHeight, OPENGL, P2D);

  for (int i = 0; i < numBalls+numBlips; i++) {
    boolean is_a_ball = i < numBalls;
    balls[i] = new Ball(random(300, 600), random(450, 650), ((is_a_ball)?(80):(10)), i, is_a_ball);
    //println( "" + i  + " " + ((is_a_ball)?(10):(80)) ); 
  }

  //smooth(); // Enabled by default.
}

int index = 0;

void draw() {
  background(0, 10);
  // For each ball,
  for (int i = 0; i < balls.length-1; i++) {
    // For all the balls after it,
    for ( int j = i+1; j < balls.length; j++) {
      // Determine if they collide.
      balls[i].collide(balls[j]);
    }
  }
  // Then move and draw all the balls.
  for (int i = 0; i < balls.length-1; i++) {
    balls[i].move();
    balls[i].display();
  }
}

class Ball {

  float x, y;
  float diameter;
  float vx = 0;
  float vy = 0;
  int id;
  boolean is_ball;

  Ball(float xin, float yin, float din, int idin, boolean iis_ball) {
    x = xin;
    y = yin;
    diameter = din;
    id = idin;
    is_ball = iis_ball;
  }    

  void collide(Ball other) {
    float dx = other.x - x;
    float dy = other.y - y;
    float distance = sqrt(dx*dx + dy*dy);
    float minDist = other.diameter/2 + diameter/2;
    if (distance < minDist) { 
      float angle = atan2(dy, dx);
      float targetX = x + cos(angle) * minDist;
      float targetY = y + sin(angle) * minDist;
      float ax = (targetX - other.x) * spring*1.1;
      float ay = (targetY - other.y) * spring*1.1;
      vx -= ax;
      vy -= ay;
      other.vx += ax;
      other.vy += ay;
    }
  }

  void move() {
    vy += gravity * (is_ball?1:2);
    x += vx;
    y += vy;
    if (x + diameter/2 > width) {
      x = width - diameter/2;
      vx *= friction;
    } else if (x - diameter/2 < 0) {
      x = diameter/2;
      vx *= friction;
    }
    if (y + diameter/2 > height) {
      y = height - diameter/2;
      vy *= friction;
    } else if (y - diameter/2 < 0) {
      y = diameter/2;
      vy *= friction;
    }
  }

  void display() {
    if ( is_ball ) {
      display_ball();
    } else { 
      display_blip();
    }
  }
  void display_ball() {
    float disc=40; 
    gradientdisc( 
      x, 
      y, 
      40, 
      disc, 
      color(0, 0, 255), 
      color(255, 255, 255) 
      ); 
    noStroke();
  }

  void gradientdisc( float x, float y, float radiusX, float radiusY, int fromC, int toC ) { 
    noStroke(); 
    beginShape(TRIANGLE_STRIP);
    int halfC = lerpColor(fromC, toC, 0.4);
    for (float theta=0; theta<TWO_PI; theta+=TWO_PI/36) { 
      fill(halfC);  
      vertex(x, y);
      if ( theta <= PI ) {
        fill(lerpColor(fromC, toC, (theta%PI)/PI ));
      } else {
        fill(lerpColor(toC, fromC, (theta%PI)/PI ));
      }
      vertex(x+radiusX*cos(theta), y+radiusY*sin(theta));
    } 
    endShape();
    float disc2=50; 
    stroke(0, 10);
    strokeWeight(1);
    noFill();
    ellipse(x, y, 100, disc2*2);
  }

  void display_blip() {
    stroke(255, 0, 144);
    strokeWeight(1);
    noFill();
    ellipse(x, y, diameter, diameter);
  }
}

Anyway, I merged the Blips with the Balls. Notice that the Ball class now has a is_ball boolean that knows if a given ball is a blip or a ball.

Also notice that there is ONLY ONE ARRAY OF OBJECTS: balls. Each single ball does not have a copy of this array!

And the collides() function is being passed a ball to check for collision against.

1 Like