Basic Java global variable question

I’m very new to object oriented programming in general, and I have a question about how to instance/work with global variables which might be caused by a lack of understanding of Java/OOP in general rather than being specific to Processing. Here I have code where I have instanced global variables which are then incremented randomly by objects of the BubbDraw class. This code worked in the Processing iOS app which I think uses an older version of Processing, however I believe the fact that the variables are instantiated outside of any function is causing an error in Processing 3 on my PC.

I’ve heard that it’s kosher to keep variables within functions, but my question is specifically where to instantiate these variables. I’m not entirely sure whether the variables need to be global, but my only concern is that the variables can’t be instantiated within the drawBubb() function because I don’t want the variables to reset every time the function is called, of course. If I have to create a new function to instantiate these variables, can anyone walk me through how and where to place this function so the variables can be accessed by the drawBubb() function?

//create rgb list
float[] rgb = new float[4];

for (int i = 0; i < 3; i++) {
   rgb[i] = random(255)
}
//initialize opacity control 
sizeoprange = 20;
rgb[3] = random(sizeoprange);

//initialize ellipse size step variables
sizestep = 1;
sizerange = 20;

//bubble class
class BubbDraw{
   void drawBubb() {
      //color increment
      for (int i = 0; i <3; i++) {
        randinc = second()%15
        
        rgb[i] += random(-randinc, randinc);
        rgb[i] = constrain(rgb[i], 50, 255);
      }
      //opacity increment
      sizeopstep = 0.2;
      sizeoprange += random(-sizeopstep, sizeopstep);
      sizeoprange = constrain(sizeoprange, 1, 100);
      rgb[3] = random(sizeoprange);
      
      fill(rgb[0], rgb[1], rgb[2], rgb[3]);

      //size increment
      sizestep = 1;
      sizerange += random(-sizestep, sizestep);
      sizerange = constrain(sizerange, 1, 40);

      sizey = random(sizerange);
      ellipse(random(width),    random(height), sizey, sizey);
   }
}

//number of objects
numbubs = 1000;

//instantiate list of objects
BubbDraw[] bubblist = new BubbDraw[numbubs]; 
for (int i = 0; i < numbubs; i++) {
  bubblist[i] = new BubbDraw();
}

void setup() {
   size(displayWidth, displayHeight);
   noStroke();
   background(0);
}

void draw() {
   for (int i = 0; i < numbubs; i++) {
  bubblist[i].drawBubb();
  }
}

Hi,

Welcome to the forum! :wink:

You can actually use what is called “class variables” by using the static keyword when declaring a member variable in your class.

Like this :

class BubbDraw {
  static int count = 0;
}

For example we declare a count variable with static that is then going to be shared among all the instances of the BubbDraw class.

That means that it’s initialized once when the class is interpreted and then all the BubbDraw objects can access it :

class BubbDraw {
  static final int count = 0;
}

BubbDraw b1 = new BubbDraw();
println(b1.count); // -> 0

BubbDraw b2 = new BubbDraw();
b2.count = 2;
println(b2.count); // -> 2
println(b1.count); // -> 2

// Also accessible with the class name if declared public/package
println(BubbDraw.count); // -> 2

The bad news is that when coding in the Processing IDE, the code you write is wrapped inside a PApplet class so you can’t actually use non final static class variables.

This is for example the exported code :

import processing.core.*; 
import processing.data.*; 
import processing.event.*; 
import processing.opengl.*; 

import java.util.HashMap; 
import java.util.ArrayList; 
import java.io.File; 
import java.io.BufferedReader; 
import java.io.PrintWriter; 
import java.io.InputStream; 
import java.io.OutputStream; 
import java.io.IOException; 

public class testStatic extends PApplet {
  public void setup() {
class BubbDraw {
  static final int count = 0;
}
    noLoop();
  }

  static public void main(String[] passedArgs) {
    String[] appletArgs = new String[] { "testStatic" };
    if (passedArgs != null) {
      PApplet.main(concat(appletArgs, passedArgs));
    } else {
      PApplet.main(appletArgs);
    }
  }
}

But in Java you can’t have a static declaration in an inner class :

In Processing, you get this error :

The field count cannot be declared static in a non-static inner type, unless initialized with a constant expression

The solution is to use Eclipse or configure a real Java project so you can use the full power of OOP with Processing.

But a workaround is also to declare the class static :

static class BubbDraw {
  static int count = 0;
}

void setup() {}

(note that it does not work when there’s no setup() function :grinning: )

4 Likes

roughly, this works in proccessing


//number of objects
int numbubs = 1000;

//instantiate list of objects
BubbDraw[] bubblist = new BubbDraw[numbubs]; 


void setup() {
  size(displayWidth, displayHeight);
  noStroke();
  background(0);

  //
  for (int i = 0; i < numbubs; i++) {
    bubblist[i] = new BubbDraw();
  }
}

void draw() {
  for (int i = 0; i < numbubs; i++) {
    bubblist[i].drawBubb();
  }
}

//==============================================================================

//bubble class
class BubbDraw {

  //create rgb list
  float[] rgb = new float[4];

  //initialize opacity control 
  float sizeoprange = 20;

  //initialize ellipse size step variables
  int sizestep = 1;
  int sizerange = 20;

  //constr
  BubbDraw() {
    for (int i = 0; i < 3; i++) {
      rgb[i] = random(255);
    }
    rgb[3] = random(sizeoprange);
  }//constr

  void drawBubb() {
    //color increment
    for (int i = 0; i <3; i++) {
      float randinc = second()%15;

      rgb[i] += random(-randinc, randinc);
      rgb[i] = constrain(rgb[i], 50, 255);
    }
    //opacity increment
    float sizeopstep = 0.2;
    sizeoprange += random(-sizeopstep, sizeopstep);
    sizeoprange = constrain(sizeoprange, 1, 100);
    rgb[3] = random(sizeoprange);

    fill(rgb[0], rgb[1], rgb[2], rgb[3]);

    //size increment
    sizestep = 1;
    sizerange += random(-sizestep, sizestep);
    sizerange = constrain(sizerange, 1, 40);

    float sizey = random(sizerange);
    ellipse(random(width), random(height), sizey, sizey);
  }
}//class
//

1 Like

Thank you for contributing this solution! This works in that there are no errors, however it seems like the bubble objects stop generating about 1 second, whereas in my original code they were continually generating. Not sure if that’s just me or not!

1 Like

you’re right!

you can change your code as you like

at the moment, the bubbles are added in setup only

1 Like

Aha! I think there is maybe some confusion about what I’m trying to do, which is understandable since I’m still new at this. So maybe I should try to explain better what I’m trying to do.

I’m trying to create an array of objects (bubbles). Every frame, I want the color of each bubble to be incremented a small amount, and the bubble to be redrawn. So I need the list of objects and the color data they contain to remain global.

When I change the bubbles from being added in setup to being added in draw, for example, it allows the bubbles to be redrawn every frame, however it gives each object its own RGB list. I want the RGB list to be global so each object can draw from it. So I need the list of objects to be created only once, and use a global RGB list, but update and re-draw every frame.

Sorry for being so long-winded. Variable scope is still difficult for me to wrap my head around sometimes!

1 Like

This means that all bubbles have the same color.

I guess. OR they access by using a value that’s individual, meaning inside the class, so each bubble can have a different value.

Did you look at lerpColor? Similar to lerp it provides a smooth transition from color A to color B, using a value amt between 0 and 1. See reference.

Please try to improve the code and post your correct code

Thank you!

Example


//number of objects
int numbubs = 1000;

int sizerange = 20;

//instantiate list of objects
BubbDraw[] bubblist = new BubbDraw[numbubs]; 

//------

//create rgb list
float[] rgb = new float[4];

//initialize opacity control 
float sizeoprange = 20;

//initialize ellipse size step variables
int sizestep = 1;


//------

void setup() {
  size(displayWidth, displayHeight);
  noStroke();

  for (int i = 0; i < 3; i++) {
    rgb[i] = random(255);
  }
  rgb[3] = random(sizeoprange);

  //
  for (int i = 0; i < numbubs; i++) {
    bubblist[i] = new BubbDraw();
  }
}

void draw() {
  background(0);

  setColor();

  for (int i = 0; i < numbubs; i++) {
    bubblist[i].drawBubb();
  }
}

//---------------------------------------------------------------

void setColor() {

  //color increment
  for (int i = 0; i <3; i++) {
    float randinc = second()%15;

    rgb[i] += random(-randinc, randinc);
    rgb[i] = constrain(rgb[i], 50, 255);
  }

  //opacity increment
  float sizeopstep = 0.2;
  sizeoprange += random(-sizeopstep, sizeopstep);
  sizeoprange = constrain(sizeoprange, 1, 100);
  rgb[3] = random(sizeoprange);

  fill(rgb[0], rgb[1], rgb[2], rgb[3]);

  //size increment
  sizestep = 1;
  sizerange += random(-sizestep, sizestep);
  sizerange = constrain(sizerange, 1, 40);
}

//==============================================================================

//bubble class
class BubbDraw {
  //
  float x, y; 
  float sizey = random(sizerange);

  //constr
  BubbDraw() {
    //
    x=random(width);
    y=random(height);
  }//constr

  void drawBubb() {
    ellipse(x, y, 
      sizey, sizey);
  }
}//class
//