Bubbles Blinking

edited April 2017 in Questions about Code

I have a pretty straight forward code written that produces bubbles across the bottom of the screen continuously, and once they reach the top they are removed. However, I've noticed random bubbles will blink a few times before they reach the top of the screen. I'm just wondering why that is.

Here's the code:

Main

ArrayList<Bubble> bubbles;
int add = 0;
int initial = 10;

void setup(){
  fullScreen();
  bubbles = new ArrayList<Bubble>();
}

void draw(){
  background(0);
  bubbles.add(new Bubble(random_generator()));

  //If bubble gets to the top it is removed
  for (int i = 0; i < bubbles.size(); i++){
    Bubble b = bubbles.get(i);
    b.ascend();
    b.display();
    if (b.top()){
      bubbles.remove(i);
    }

  }
}

int random_generator(){
  int r = int(random(10, 100));
  return r;
}

Class

class Bubble{

  float x;
  float y;
  float diameter;
  float yspeed;

  //constructor
  Bubble(float tempD){
    x = random(width);
    y = height;
    diameter = tempD;
    yspeed = random(2.5, 10.5);
  }

  //moves bubble upwards, and randomly from side-to-side
  void ascend(){
    y = y - yspeed;
    x = x + random(-2, 2);
  }

  //displays bubble
  void display(){
    noStroke();
    fill(231, 254, 255, 200);
    ellipse(x, y, diameter, diameter);
  }

  //checks if bubble is at the top of the screen
  boolean top(){
    if (y < 0){
      return true;
    }
    else{
      return false;
    }
  }
}

Answers

  • edited April 2017 Answer ✓

    When you remove a bubble, the bubble immediately after it in the ArrayList blinks.

    Imagine bubbles A[9], B[10], and C[11]. A reaches the top, and so bubble [9] is removed. Now bubble B[10] becomes B[9], because the old A[9] is gone. But your loop has already displayed [9] -- it moves on to displaying C[10], and B is not displayed for that frame only. Hence the flicker.

    To fix this problem, always loop backwards using -- through any ArrayList if you will be removing items, e.g.:

    for (int = bubbles.size(); i>0; i--){
    
  • Never mind, I fixed it. I just went through the Arraylist in reverse.

     for (int i = bubbles.size()-1; i >= 0; i--){
        Bubble b = bubbles.get(i);
        b.ascend();
        b.display();
        if (b.top()){
          bubbles.remove(i);
        }
    

    So, I guess going forward it wasn't checking every element in the array? Not exactly sure?

  • edited April 2017 Answer ✓

    Looping backwards is the easiest solution for remove(). :-B
    But still there's a way to use forward looping, as long as we decrease the iterator & total size by 1 every time remove() is invoked. :ar!

  • Ah, yes, that works too.

    Awesome! Thanks.

  • If I wanted to change the colors of the bubbles, say varying through the visible light color scale (ROYGBV), what would be the best way to do that?

    I thought of having three variables 'r', 'b', and 'g' and setting them all to 255 then decreasing them randomly (r--, b--, g--), then setting them back if they reach 0. But you'd have to do that in the right order and at the right time to get the correct rainbow effect. Just wondering if there's an easier and/or more efficient way to accomplish this?

  • @PRouse --

    For a single variable to control rainbow shifting, use colorMode(HSB, 360) ....(or 100, or 255, or 1.0 -- whatever max you choose).

  • edited April 2017

    So, I sort of understand the examples, but I'm not exactly sure how that's going to translate to my bubbles? Here's the redo of my class which I just decreased/variables variables according to height of the bubble:

    class Bubble{
    
      float x;
      float y;
      float diameter;
      float yspeed;
      float b = 0;
      float g = 0;
      float r = 50;
    
      //constructor
      Bubble(float tempD){
        x = random(width);
        y = height;
        diameter = tempD;
        yspeed = random(1.5, 2.5);
      }
    
      //moves bubble upwards, and randomly from side-to-side
      void ascend(){
        y = y - yspeed;
        x = x + random(-2, 2);
      }
    
      //displays bubble
      void display(){
        noStroke();
        fill(r, g, b, 220);
        if(y <= height && y > height - 180){
          r++;
        }
        if(y <= height - 180 && y > height - (180*2)){
          r-=0.2;
          g+=0.5;
        }
        if(y <= height - (180*2) && y > height - (180*3)){
          g++;
          r+=0.5;
        }
        if(y <= height - (180*3) && y > height - (180*4)){
          r--;
          b+=0.2;
        }
        if(y <= height - (180*4) && y > height - (180*5)){
          g--;
          b+=1.5;
        }
        if(y <= height - (180*5) && y > height - (180*6)){
          r++;
        }
        ellipse(x, y, diameter, diameter);
      }
    
    
      //checks if bubble is at the top of the screen
      boolean top(){
        if (y < 0){
          return true;
        }
        else{
          return false;
        }
      }
    }
    

    My height for full screen is 1080, so I just divided that by 6 (ROYGBV) which gives 180. What exactly makes using colorMode() more useful here? I mean do I set the colorMode() and then use for loops to set each RGB fill value...or HSB value to change each bubble's color over as it ascends?

Sign In or Register to comment.