I need help creating an array of bouncy balls with text and info displayed

edited October 2017 in Questions about Code

Hi,

I am trying to create a code to display earthquake data sets but I'm teaching myself processing and I am struggling...

I want to display the worlds largest 10 earthquakes in history. Each bouncy ball should be a different size depending on the size of the earthquake and when the mouse hovers over one ball information appears (location, date, magnitude). When this hover happens I want the screen to freeze so it's easier for the information to be read.

At the moment I have a code that has 12 bouncy balls but I can't work out how to place individual text on specific balls - right now the same text line is displayed on all the balls and when the program is closed and re-run this text changes but is still displayed on every circle.

I think most of my problems are coming because I haven't created an array of the bouncing balls but I don't know how to do that I keep getting an error message. I still want my bouncing balls to bounce off each other with no gravity.

If anyone could help me to put my 6 country names on 6 different bouncing balls and create a mouse hover code for me that would be very helpful! And if anyone can, could you display this data on one ball:

  • name = indonesia

  • date = 2004

  • magnitude = 9.1

My code so far looks like this:

int numBalls = 12;
float spring = 0.05;
float friction = -0.9;
Ball[] balls = new Ball[numBalls];

float r = random(6);

String[] headlines = {"Indonesia", "Australia", "Japan", "Mexico", "USA", "Germany"};

String c = headlines[int(random(6))];

PFont f;



void setup() {
size(1275, 700);
for (int i = 0; i < numBalls; i++) {
//array
balls[i] = new Ball(random(width), random(height), random(100, 100), i, balls);
//need to make array of different size circles then line underneath for text
}
noStroke();
fill(255, 204);
f = createFont("arial",20,true);  
}

void draw() {
background(0);

//adding text
fill(255,255,255);
String s= "WORLD'S LARGEST QUAKES";
textSize(64);
text(s,500,100);

for (Ball ball : balls) {
ball.collide();
ball.move();
ball.display(); 
}
}



class Ball {

float x, y;
float diameter;
float vx = 0;
float vy = 0;
int id;
Ball[] others;

Ball(float xin, float yin, float din, int idin, Ball[] oin) {
x = xin;
y = yin;
diameter = din;
id = idin;
others = oin;
} 

void collide() {
for (int i = id + 1; i < numBalls; i++) {
  float dx = others[i].x - x;
  float dy = others[i].y - y;
  float distance = sqrt(dx*dx + dy*dy);
  float minDist = others[i].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 - others[i].x) * spring;
    float ay = (targetY - others[i].y) * spring;
    vx -= ax;
    vy -= ay;
    others[i].vx += ax;
    others[i].vy += ay;
  }
}   
}

void move() {
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() {
//fill ellipse
fill(0,255,0);
ellipse(x, y, diameter, diameter);
//fill text
fill(255,255,255);
textFont(f,20);
textAlign(CENTER);
text(c,x,y);
}
}
Tagged:

Answers

  • Thank you!

  • edited October 2017

    One approach:

    Your class "Ball" should have a variable "String name" in it. You should assign the name in the class constructor, when you create a Ball. You can then print the name of a ball with text(this.name) in your display function when you display() your ball -- or create a separate mouseover, etc.

  • In your draw() function, you need first to iterate through your items to see if any of the ellipses is close to your mouse pointer. If so, you need to make sure the move() function of each ellipse is not executed. Consider:

    void draw(){
    
     [... SOME OMITTED code]
    
      //STEP1
      boolean stopBalls=false;  //Reset
      Ball ballText=null;
      for (Ball ball : balls) {
        stopBalls=ball.hover();
        if(ball.hover()==true)  ballText=ball;
      }
    
      //STEP2
      for (Ball ball : balls) {
        ball.collide();
        if(stopBalls==false) {
          ball.move();
        } 
        ball.display();
      }
    
      //STEP3
      if(stopBalss==true){
        ballText.displayHoverText();
      }
    
    }//END of draw
    

    Now you need to implement your member functions hover() and displayHoverText() within your Ball class:

    boolean hover(){
      return dist(mouseX,mouseY,x,y) < diamter/2.0;
    }
    
    boolean displayHoverText(){
      text(id+" at Pos " + x +", " + y,x,y);
    }
    

    This is untested code to show the concept. To clarify, this is only one way to do this based on the information provided. To consider: What needs to be change if two balls are equidistant to the mouse pointer?

    Kf

  • Thank you - I think I understand this and I have tried to enter it into my code but could you just clarify do I put the second paragraph of code underneath what pre-exists in 'class Ball'? And there is now an error when i try to run the program - unexpected token: boolean. Do you have any ideas how I would correct this?

  • post your entire code please

    do I put the second paragraph of code underneath what pre-exists in 'class Ball'?

    Yes but before the class closing }

    unexpected token: boolean

    probably misplaced { or so

  • edited October 2017

    this is what i have so far - still having some trouble with the boolean error though

    int numBalls = 12;
    float spring = 0.05;
    float friction = -0.9;
    Ball[] balls = new Ball[numBalls];
    
    float r = random(6);
    
    String[] headlines = {"Indonesia", "Australia", "Japan", "Mexico", "USA", "Germany"};
    
    String c = headlines[int(random(6))];
    
    PFont f;
    
    
    
    void setup() {
    size(1275, 700);
    for (int i = 0; i < numBalls; i++) {
    //array
    balls[i] = new Ball(random(width), random(height), random(100, 100), i, balls);
    //need to make array of different size circles then line underneath for text
    }
    noStroke();
    fill(255, 204);
    f = createFont("arial",20,true);  
    }
    
    void draw() {
    background(0);
    //background
    background(255,255,255);
    //background
    noStroke();
    fill(#BDC3C7);
    rect(0,0,1275,500);
    noStroke();
    fill(#283747);
    rect(0,1275,700,300);
    //text
    fill(255,255,255);
    String s= "WORLD'S LARGEST QUAKES";
    textSize(64);
    text(s,0,400);
    
    
    
    //STEP1
    boolean stopBalls=false;  //Reset
    Ball ballText=null;
    for (Ball ball : balls) {
    stopBalls=ball.hover();
    if(ball.hover()==true)  ballText=ball;
    }
    
    
    //step 2
    for (Ball ball : balls) {
    ball.collide();
    if (stopBalls==false){
    ball.move();
    }
    ball.display(); 
    }
    
    //STEP3
    if(stopBalls==true){
    ballText.displayHoverText();
    }
    }
    
    
    
    class Ball {
    
    float x, y;
    float diameter;
    float vx = 0;
    float vy = 0;
    int id;
    Ball[] others;
    
    Ball(float xin, float yin, float din, int idin, Ball[] oin) {
    x = xin;
    y = yin;
    diameter = din;
    id = idin;
    others = oin;
    
    
    
    boolean hover(){
    return dist(mouseX,mouseY,x,y) < diamter/2.0;
    }
    
    boolean displayHoverText(){
    text(id+" at Pos " + x +", " + y,x,y);
    }
    }
    
    
    void collide() {
    for (int i = id + 1; i < numBalls; i++) {
      float dx = others[i].x - x;
      float dy = others[i].y - y;
      float distance = sqrt(dx*dx + dy*dy);
      float minDist = others[i].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 - others[i].x) * spring;
        float ay = (targetY - others[i].y) * spring;
        vx -= ax;
        vy -= ay;
        others[i].vx += ax;
        others[i].vy += ay;
    }
    }   
    }
    
    void move() {
    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() {
    //fill ellipse
    fill(0,255,0);
    ellipse(x, y, diameter, diameter);
    //fill text
    fill(255,255,255);
    textFont(f,20);
    textAlign(CENTER);
    text(c,x,y);
    }
    }
    
  • int numBalls = 12;
    float spring = 0.05;
    float friction = -0.9;
    Ball[] balls = new Ball[numBalls];
    
    float r = random(6);
    
    String[] headlines = {"Indonesia", "Australia", "Japan", "Mexico", "USA", "Germany"};
    
    String c = headlines[int(random(6))];
    
    PFont f;
    
    
    
    void setup() {
      size(1275, 700);
      for (int i = 0; i < numBalls; i++) {
        //array
        balls[i] = new Ball(random(width), random(height), random(100, 100), i, balls);
        //need to make array of different size circles then line underneath for text
      }
      noStroke();
      fill(255, 204);
      f = createFont("arial", 20, true);
    }
    
    void draw() {
      background(0);
      //background
      background(255, 255, 255);
      //background
      noStroke();
      fill(#BDC3C7);
      rect(0, 0, 1275, 500);
      noStroke();
      fill(#283747);
      rect(0, 1275, 700, 300);
      //text
      fill(255, 255, 255);
      String s= "WORLD'S LARGEST QUAKES";
      textSize(64);
      text(s, 0, 400);
    
    
    
      //STEP1
      boolean stopBalls=false;  //Reset
      Ball ballText=null;
      for (Ball ball : balls) {
        stopBalls=ball.hover();
        if (ball.hover()==true)  ballText=ball;
      }
    
    
      //step 2
      for (Ball ball : balls) {
        ball.collide();
        if (stopBalls==false) {
          ball.move();
        }
        ball.display();
      }
    
      //STEP3
      if (stopBalls==true) {
        ballText.displayHoverText();
      }
    }
    
    
    
    class Ball {
    
      float x, y;
      float diameter;
      float vx = 0;
      float vy = 0;
      int id;
      Ball[] others;
    
      Ball(float xin, float yin, float din, int idin, Ball[] oin) {
        x = xin;
        y = yin;
        diameter = din;
        id = idin;
        others = oin;
      }
    
    
      boolean hover() {
        return dist(mouseX, mouseY, x, y) < diameter/2.0;
      }
    
      void displayHoverText() {
        text(id+" at Pos " + x +", " + y, x, y);
      }
    
    
    
      void collide() {
        for (int i = id + 1; i < numBalls; i++) {
          float dx = others[i].x - x;
          float dy = others[i].y - y;
          float distance = sqrt(dx*dx + dy*dy);
          float minDist = others[i].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 - others[i].x) * spring;
            float ay = (targetY - others[i].y) * spring;
            vx -= ax;
            vy -= ay;
            others[i].vx += ax;
            others[i].vy += ay;
          }
        }
      }
    
      void move() {
        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() {
        //fill ellipse
        fill(0, 255, 0);
        ellipse(x, y, diameter, diameter);
        //fill text
        fill(255, 255, 255);
        textFont(f, 20);
        textAlign(CENTER);
        text(c, x, y);
      }
    }
    //
    
  • edited October 2017

    a few remarks

    you had a missing / mis-placed bracket } here:

     Ball(float xin, float yin, float din, int idin, Ball[] oin) {
        x = xin;
        y = yin;
        diameter = din;
        id = idin;
        others = oin;
    
       // }   this } as missing (or came further down after the functions hover and displayHoverText. 
    
    
      boolean hover() {
    

    Remark

    This is a function

      boolean hover() {
        return dist(mouseX, mouseY, x, y) < diameter/2.0;
      }
    

    it starts with the word boolean since it returns a boolean value (using the word return to return it.)

    this is also a function

      void displayHoverText() {
        text(id+" at Pos " + x +", " + y, x, y);
      }
    

    but it doesn't return anything, so we just say void, empty, as return type.

    (you had boolean displayHoverText() here, but it doesn't return a boolean)

    (functions in a class are called methods, but same thing)

This discussion has been closed.