[SOLVED] PImage[] array inside class shows all images at once

Please note that this is just a portion of the full code. I made sure to isolate this portion only, with all its problems included.

What it’s supposed to do:
So, in the full code I have a program where you can hit a certain key and it will spawn 2D moons in an orbit. Now, these moons have their own class and they’re simply ellipses. I also have another class for planets. The difference here is that they are images.

What it actually does:
Take it back to the same scenario where you would hit a key and a moon would pop up and apply that to the planets class. Instead, it only pops up for a split second and it shows all images in the array at once. Now I’ve tried to do this with booleans as well, but the problem still existed, so here’s me hoping someone knows how to help me out.

I could only upload one image, but you’ll get the idea.

Planet planetTex;

float x = 500;
float y = 110;

void setup(){
  size (1600, 800);
  
  planetTex = new Planet();
}

void draw() {
  background(0);
  
  planetTex.planetImgIni();
}

class Planet {
  PImage[] planetDiffuse = new PImage[2];

  Planet() {
    for (int i = 0; i < planetDiffuse.length; i++) {
      planetDiffuse[i] = loadImage("land" + i + ".png");
    }
  }

  void planetImgIni() {
    if (keyPressed == true) {
      if (key == 'a') {
        image(planetDiffuse[int(random(planetDiffuse.length))], x, y);
      }
    }
  }
}

1 Like

looks like you show

image(img,x,y) ;

only once when ?a key is pressed?


try to use the keyPressed function
and if key [a] is pressed
toggle a class boolean variable

boolean showit = false;

and use it for the show

 if ( showit ) image(img,x,);

add:

void keyPressed() {}
  if ( key == 'a' ) planets[0].showit = ! planets[0].showit;
1 Like

I tried you method and it tells me the global variable “showit” does not exist. I may have done something wrong.

boolean showit = false;

PImage[] planetDiffuse = new PImage[2];

float x = 500;
float y = 110;

void setup() {
  size (1600, 800);

  for (int i = 0; i < planetDiffuse.length; i++) {
    planetDiffuse[i] = loadImage("land" + i + ".png");
  }
}

void draw() {
  background(0);

  if (showit) {
    image(planetDiffuse[int(random(planetDiffuse.length))], x, y);
  }
}

void keyPressed() {
  if (key == 'A') {
    planetDiffuse[0].showit = ! planetDiffuse[0].showit;
  }
}

1 Like

Hey There!

The showit variable is not part of the PImage ! It is a standalone as a global but it isn’t part of the PImage. change the code to

void keyPressed() {
  if (key == 'A') {
    showit = true;
  }
}
1 Like

Thanks for your input. I’ve already tried this method and the problem still occurs where all images in the array are displayed at once and as a result they all flicker through each other.

1 Like

Hmm interesting let me have a go ! And I will comeback to you and see what I figure out !

Hey it me again !

So I believe what your problem is that you hit the key and they only appear for a second right ? Then the boolean ‘stop key’ isn’t correct. But the answer I gave previously should have solved it. But here’s a more sophisticated example.


Planets planetTex;
float x = 500;
float y = 110;
void setup() {
  size (800, 640);
  planetTex = new Planets();
}

void draw() {
  background(0);
  planetTex.pickedPlanet();
}
void keyPressed() {
  if(keyCode == 'A' && !planetTex.getPressed()) planetTex.pressed(true);
  else if(keyCode == 'A' && planetTex.getPressed() ) planetTex.pressed(false);
}
class Planets {
  PImage[] planetDiffuse = new PImage[2];
  boolean chosen;
  Planets() {
    planetDiffuse[0] = loadImage("earth.png");
    planetDiffuse[1] = loadImage("earth2.png");
    chosen = false;
  }
  void pickedPlanet() {
    if ( chosen ) {
      for (int i = 0; i < planetDiffuse.length; i++) {
        image(planetDiffuse[i], i%width, i%height);
      }
    }
  }
  boolean pressed(boolean hitKey) {
    return chosen = hitKey;
  }
  boolean getPressed(){
    return chosen;  
  }
}

Does this fix your issue ?

Also a note. Your images will be flickering as when you haveshowit = true; A random number is picked in the draw method every single time the draw() is called. This should only be done per press not inside the draw method as it executes 60 FPS. That what was causing your issue as your picking a new image 60 FPS.

if (showit) {
    image(planetDiffuse[int(random(planetDiffuse.length))], x, y);
  }
3 Likes

Thank you for your reply!:blush:

I tested the code out and it looks good, because the images are indeed no longer flickering - so my biggest concern is gone.

However, currently when I press ‘a’, both images are shown at once. It may be because of my sloppy explanation, but it’s supposed to show one image at a time every time ‘a’ is pressed.

Also, my intentions were to bind a single key to spawn a new image every time that key was pressed. This would indeed mean that the new image would be drawn over the old image and that’s fine with me. But they don’t have to be turned off once they’re spawned. That’s way too fancy for my level of knowledge in Processing :grin:

To get one image picked (let go random) you can just whenever the pressed method is executed before the return statement you can add a class variable rand ( call it whatever this uses the length of the array and will display that image in pickedPlanet() (remove the for loop from there too ).

It didn’t give me anything new unfortunately. I’m still bumping against the previous problems.

Here’s the full initial code to my little program. Perhaps that clears things up a bit more. Note that I have 4 images of planets in my data folder called planet0.png, planet1.png, planet2.png and planet3.png.

JSONArray values;
ArrayList<Moon> manen = new ArrayList<Moon>();
ArrayList<Clouds> wolken = new ArrayList<Clouds>();

boolean planetSpawn = false;

PImage matte;

PImage temp; //screenshot
int saveP = 1;

PImage[] PlanetLand = new PImage[4];

float x = 500;
float y = 110;
float diameter = 600;

Planet planeet;

void setup() {
  size(1600, 800);
  planeet = new Planet();
  matte = loadImage("matte.png"); 

  for (int i = 0; i < PlanetLand.length; i++) {
    PlanetLand[i] = loadImage("land" + i + ".png");
  }
}

void draw() {
  background(0);

  for (Clouds b : wolken) {
    b.cloudPuff();
  }

  image(matte, 0, 0); //obscure layer for clouds

  for (Moon a : manen) {
    a.orbitLines();
    a.whiteCirkel();
  }

  planeet.planetSpawnHere();
}

void keyPressed() {
  if (key == '1') {
    manen.add(new Moon(random(200, 380), random(20, 100), random(5, 45), random(0.002, 0.05), color(random(255), random(255), random(255))));
  }

  if (key == '2') {
    wolken.add(new Clouds(random(30, 75), random(15, 30), random(150, 600), random(250, 350), random(0, 10)));
  }

  if (key == 'a') {
    planetSpawn = true;
  }
}

void keyTyped() {
  if (key == '0') {
    PImage temp = get(415, 0, 770, 800); 
    temp.save("MyPlanet_" + saveP + ".png"); 
    saveP++;
  }
}




class Clouds {
  float widthClouds, heightClouds;
  float x, y;
  float speed;
  float start;

  Clouds(float tempWidth, float tempHeight, float tempVertical, float tempStart, float tempSpeed) {
    widthClouds = tempWidth;
    heightClouds = tempHeight;
    x = 500;
    y = tempVertical;
    start = tempStart;
    speed = tempSpeed;
  }

  void cloudPuff() {
    for (int i = 0; i < speed; i++) {
      if (x > 1050) {
        x = start;
      }
      x = x + 1;
    }

    noStroke();
    fill(240);
    rect(x, y, widthClouds, heightClouds, 250);
  }
}




class Moon {
  float x, y;
  float radius;
  int centX;
  int centY;
  float ang;
  float angspeed;
  float sizeMoon;
  color kleur;

  Moon(float tempRadius, float tempAng, float tempMoonSize, float tempAngSpeed, color tempKleur) {
    radius = tempRadius;
    centX = width/2;
    centY = height/2;
    ang = tempAng;
    angspeed = tempAngSpeed;
    sizeMoon = tempMoonSize;
    kleur = tempKleur;
  }

  void orbitLines() {
    stroke(kleur);
    strokeWeight(2);
    noFill();
    ellipse(centX, centY, radius * 2, radius * 2);
  }

  void whiteCirkel() {
    stroke(kleur);
    strokeWeight(1);
    fill(kleur);
    ellipse(x, y, sizeMoon, sizeMoon);

    x = centX + (radius * cos(ang));
    y = centY + (radius * sin(ang));

    ang = ang + angspeed;
  }
}




class Planet {
  PImage[] planetDiffuse = new PImage[4];

  Planet() {
    for (int i = 0; i < planetDiffuse.length; i++) {
      planetDiffuse[i] = loadImage("land" + i + ".png");
    }
  }

  void planetSpawnHere() {
    if (planetSpawn) {
      image(PlanetLand[int(random(PlanetLand.length))], x, y);
      //planetSpawn = false;
    }
  }
}
1 Like

You are still doing the same issue ! You are calling planet spawn from draw ! The random num will be picked 60 FPS ! Hence causing the flickering. Again to avoid this you can make a variable inside the class + a method for e.g. called rand and getRandomNum and put it inside your Planet clas the keypressed where it will be called from. This will ensure that only a random picture is picked per key press.

I’m sorry, I’m afraid I don’t follow. I understand I shouldn’t place the planetspawnHere() in the draw but where does this piece of code go then?

 image(PlanetLand[int(random(PlanetLand.length))], x, y);

If you have time, could you show me specifically where in the code, please?

1 Like

No problem to show you ! This line is called within planetSpawnHere() the issue is the random() as everytime the method is entered it will go and get a different image. That is why we shouldn’t calculate a random number at every iteration but just ‘sometimes’ for example when you press a key ( that up to you how often , but remember to much and it will flicker ) but if you leave getting the random number being calculated in draw() it will keep causing the flickering!

image(PlanetLand[int(random(PlanetLand.length))], x, y);

Here’s code which accommodates what I meant earlier.

JSONArray values;
ArrayList<Moon> manen = new ArrayList<Moon>();
ArrayList<Clouds> wolken = new ArrayList<Clouds>();

boolean planetSpawn = false;

PImage matte;

PImage temp; //screenshot
int saveP = 1;

PImage[] PlanetLand = new PImage[4];

float x = 500;
float y = 110;
float diameter = 600;

Planet planeet;

void setup() {
  size(1600, 800);
  planeet = new Planet();
  matte = loadImage("matte.png"); 

  for (int i = 0; i < PlanetLand.length; i++) {
    PlanetLand[i] = loadImage("land" + i + ".png");
  }
}

void draw() {
  background(0);

  for (Clouds b : wolken) {
    b.cloudPuff();
  }

  image(matte, 0, 0); //obscure layer for clouds

  for (Moon a : manen) {
    a.orbitLines();
    a.whiteCirkel();
  }

  planeet.planetSpawnHere();
}

void keyPressed() {
  planeet.getRandom();
  if (key == '1') {
    manen.add(new Moon(random(200, 380), random(20, 100), random(5, 45), random(0.002, 0.05), color(random(255), random(255), random(255))));
  }

  if (key == '2') {
    wolken.add(new Clouds(random(30, 75), random(15, 30), random(150, 600), random(250, 350), random(0, 10)));
  }

  if (key == 'a') {
    planetSpawn = true;
  }
}

void keyTyped() {
  if (key == '0') {
    PImage temp = get(415, 0, 770, 800); 
    temp.save("MyPlanet_" + saveP + ".png"); 
    saveP++;
  }
}




class Clouds {
  float widthClouds, heightClouds;
  float x, y;
  float speed;
  float start;

  Clouds(float tempWidth, float tempHeight, float tempVertical, float tempStart, float tempSpeed) {
    widthClouds = tempWidth;
    heightClouds = tempHeight;
    x = 500;
    y = tempVertical;
    start = tempStart;
    speed = tempSpeed;
  }

  void cloudPuff() {
    for (int i = 0; i < speed; i++) {
      if (x > 1050) {
        x = start;
      }
      x = x + 1;
    }

    noStroke();
    fill(240);
    rect(x, y, widthClouds, heightClouds, 250);
  }
}




class Moon {
  float x, y;
  float radius;
  int centX;
  int centY;
  float ang;
  float angspeed;
  float sizeMoon;
  color kleur;

  Moon(float tempRadius, float tempAng, float tempMoonSize, float tempAngSpeed, color tempKleur) {
    radius = tempRadius;
    centX = width/2;
    centY = height/2;
    ang = tempAng;
    angspeed = tempAngSpeed;
    sizeMoon = tempMoonSize;
    kleur = tempKleur;
  }

  void orbitLines() {
    stroke(kleur);
    strokeWeight(2);
    noFill();
    ellipse(centX, centY, radius * 2, radius * 2);
  }

  void whiteCirkel() {
    stroke(kleur);
    strokeWeight(1);
    fill(kleur);
    ellipse(x, y, sizeMoon, sizeMoon);

    x = centX + (radius * cos(ang));
    y = centY + (radius * sin(ang));

    ang = ang + angspeed;
  }
}




class Planet {
  PImage[] planetDiffuse = new PImage[4];
  int rand;
  Planet() {
    for (int i = 0; i < planetDiffuse.length; i++) {
      planetDiffuse[i] = loadImage("land" + i + ".png");
    }
	rand = 0;
  }

  void planetSpawnHere() {
    if (planetSpawn) {
      image(PlanetLand[rand], x, y);
      //planetSpawn = false;
    }
  }
  void getRandom(){
	rand = int(random(PlanetLand.length));
  }
}
2 Likes

Huge thanks!! That did it. I now see what you meant with the variable inside the class. I had no idea what to make of it, so again thanks for helping out! :slightly_smiling_face:

1 Like