Random Image Using an Array

Hi, I’m trying to use oop to select a random image when the mouse is clicked. I get the image to come up, but I need help making the mouse click display the new image. Sorry, not sure what to do about images in my sketch.

PImage [] fruit = new PImage[3];

Names name;

int index;

void setup(){
  size(300,300);
  fruit[0] = loadImage("apple.jpg");
  fruit[1] = loadImage("orange.jpg");
  fruit[2] = loadImage("pear.jpg");
  
  name = new Names(fruit[index]);
}

void draw(){
}

void mousePressed(){
  background(0);
  index = int(random(0,fruit.length));
  name.display();
  println(index);
}

class Names{
  
 PImage img;
 
 Names(PImage tempImg){
   img = tempImg;
 }
 
 void display(){
   stroke(0);
   imageMode(CENTER);
   img.resize(200,200);
   image(img,width/2,height/2);
 }
}

You could make each of your images into an array of name objects? Like this:

Names[] name = new Names[fruit.length]; //add this under your fruit array initialization

Then you could do this in setup:

for(int i = 0; i<fruit.length; i++)
{
name[i] = new Names(fruit[i]); //set each index of the Names object to the corresponding index in your fruit array 
}

Also, where you declare index, initialize it to some value, like this:

int index = 0;

And then in your display() function?

Have something to do with the random index, like this:

void display(){
   stroke(0);
   imageMode(CENTER);
   img = name[index]; //set the random index here!
   img.resize(200,200);
   image(img,width/2,height/2); 
 }

And everything should work as you intended. The main problem you were having, was that even after changing the index, your display function inside your Names object didn’t know about the change, which is why nothing happened. Hopefully this helps!

EnhancedLoop7

1 Like

Thanks for looking at it! I followed your input, but am still having trouble - an error on the name.display() line - ‘cannot invoke display() on array type’. What am I missing?

PImage [] fruit = new PImage[3];
int index = 0;
Names[] name = new Names[fruit.length];

void setup(){
  size(300,300);
  
  fruit[0] = loadImage("apple.jpg");
  fruit[1] = loadImage("orange.jpg");
  fruit[2] = loadImage("pear.jpg");
 
  for(int i = 0; i < fruit.length; i++){
    name[i] = new Names(fruit[i]);
  }
}

void draw(){
}

void mousePressed(){
  background(0);
  index = int(random(0,fruit.length));
  name.display();
  println(index);
}

class Names{
  
 PImage img;
 
 Names(PImage tempImg){
   img = tempImg;
 }
 
 void display(){
   stroke(0);
   imageMode(CENTER);
   img = name[index];
   img.resize(200,200);
   image(img,width/2,height/2);
 }
}

Haha yes, you can’t display the WHOLE array, my bad for not mentioning, you would do something like name[index].display(). And actually, because of that, I believe you don’t even have to add in the img = name[index]; part I told you before! :smiley:

(Because the randomly selected index will apply in the name[index].display() call that you won’t have to set the image equal to the index in the display function.)

Hopefully that works!

EnhancedLoop7

Works! Thanks for your help! :grinning:

1 Like

No problem, I’m glad to help! :smiley:

EnhancedLoop7

My next step is I want to add a second array that has the names of the fruits, so that on each click the image and correct name come up together.

  • Is this best done with a second single array []? Or do I want to use a double array[] []? In looking around, I also saw hashMap and was wondering if that’s a choice.
  • Would I want a second method in the class so I have display() for the image and a second display method for the word that are connected to the same variable?

Looking for some direction. Thanks!

Actually a class would work here better. I think you want to have a tile that when you click you see the image?

Since you mention OOP in your first post, this is my suggestion, a pseudo-code:

class Tile{

  //Memeber variables
  PImage img;
  String name;
  boolean showImage;  //True show picture, else show text

  Tile(String aName, PImage anImg){
      name=aName;
      img=anImg;
      showImage=false;
  }

  void display(){
      if(showImage) displayImage();
      else showName();
  }

   void displayImage(){
       ...  To be implemented
   }

   void displayName(){
       ...  To be implemented
   }
}

Notice this class is the backbone. When you work in your implementation, you will notice that you need some sort of coordinates and fields to show either the image or the text. For instance: text(name,posX,posY);. Now, since you are working with OOP concepts, where and when would you define those fields like posX, posY and possibly the width and the height of the displaying area of these elements? (This is for you to consider)

Related to management of name/images, if you are using a fix number of name/image pairs, then you could use an array. Otherwise, use a list container like an ArrayList.

final int N=10;
Tile[] myTiles;

void setup(){
  size(300,300);

  myTiles=new Tile[N];

  myTiles[0]=new Tile("name", loadImage("your image location.jpg"));
  myTiles[1]=... etc.

  ...
}

Kf

1 Like

I have an arraylist that uses mouse clicks to select random elements, which are then removed from the list. When the list is empty, I want to refresh with a click and start over. The way I am trying this is by creating a new list, adding removed elements to it, then setting the old list equal to it.

    myTiles = newTiles;//refresh myTiles with all elements
    newTiles.clear();//clear newTiles to start over
 

It’s not quite working. Help appreciated. Here’s all the code:

int index;

//array of Tile objects
ArrayList <Tile> myTiles = new ArrayList <Tile>();

//also create a second array list to 'reset' from
ArrayList <Tile> newTiles = new ArrayList <Tile>();

void setup(){
  background(0);
  size(300,300);
    
  myTiles.add(new Tile("apple", loadImage("fruit0.jpg")));
  myTiles.add(new Tile("orange", loadImage("fruit1.jpg")));
  myTiles.add(new Tile("pear", loadImage("fruit2.jpg")));
  
  textAlign(CENTER);
  textSize(35);
  text("Random Fruits",width/2,height/3);
  text("Click to play",width/2,2*height/3);
}

void draw(){
}

void mouseClicked(){
  if(myTiles.size() > 0){
    index = int(random(myTiles.size()));
    myTiles.get(index).display();
    
  }else{
    background(0);
    textSize(25);
    text("Out of Names", width/2,height/3);
    text("Click to Play Again", width/2,2*height/3);

    myTiles = newTiles;//refresh myTiles with elements
    newTiles.clear();//clear newTiles to start over
 }
  }
}

//Tile object 
class Tile{  //Tile knows an image and name
  
 PImage img;  //pulls in image
 String item;  //pulls in name
 
 
 Tile(String tempItem, PImage tempImg){//constructor
   item = tempItem;  //name pulled in
   img = tempImg;  //image pulled in
 }
 
 void display(){
   background(0);
   textSize(70);
   fill(255,0,0);
   text(item, width/2, 3*height/4);
   
   imageMode(CENTER);
   img.resize(100,100);
   image(img,width/2,height/4);
   
   myTiles.remove(index);
   newTiles.add(new Tile(item,img));
 }
}

I am afraid you are doing it wrong. The reason is that you are doing something ilegal. You are modifying the array of tiles inside the tile class.

Think about the Tile to be an object. Think about the array to be a container of the selected objects.

For your program:

  1. You create a container and defined what type of objects it will hold
  2. You create an object and add it to the container (Do this as many times as needed)

Now, if you want to access an object, you iterate through the array. If you need to remove an object, you can do it. However, it has to be done in the global scope and not inside the class.

Consider studying the following code. For OOP, check this tutorial.

Notice I am resizing the image right after I load them. This is more efficient that resizing the image every time it is drawn. It is a minor optimization at this point, but more for you to think about it.

Kf

final int UNDEFINED=-1;

int index=UNDEFINED;

//array of Tile objects
ArrayList <Tile> myTiles = new ArrayList <Tile>();

//also create a second array list to 'reset' from
ArrayList <Tile> newTiles = new ArrayList <Tile>();

void setup() {
  background(0);
  size(300, 300);
  imageMode(CENTER);
  textAlign(CENTER);


  fillContainer();
}


void draw() {
  background(0);
  if (index!=UNDEFINED) {
    myTiles.get(index).display();
  } else {
    textSize(35);
    text("Random Fruits", width/2, height/3);
    text("Click to play", width/2, 2*height/3);
  }
}

void mouseClicked() {

  if (index==UNDEFINED) {
    background(0);
    textSize(25);
    text("Out of Names", width/2, height/3);
    text("Click to Play Again", width/2, 2*height/3);

    fillContainer();
    index = int(random(myTiles.size()));
    return;  //Forces exiting the current function
  }

  if (myTiles.size() > 1) {
    myTiles.remove(index);
    index = int(random(myTiles.size()));
  } else { 
    //THIS remove the last tile
    myTiles.remove(index);
    index=UNDEFINED;
  }
}


void fillContainer() {
  myTiles.clear();
  PImage img;
  
  img=loadImage("pic15.jpg");
  img.resize(100, 100);
  myTiles.add(new Tile("apple", img));
  
  img=loadImage("pic16.jpg");
  img.resize(100, 100);
  myTiles.add(new Tile("orange", img));
  
  img=loadImage("pic17.jpg");
  img.resize(100, 100);
  myTiles.add(new Tile("pear", img));
}

//Tile object 
class Tile {  //Tile knows an image and name

  PImage img;  //pulls in image
  String item;  //pulls in name


  Tile(String tempItem, PImage tempImg) {//constructor
    item = tempItem;  //name pulled in
    img = tempImg;  //image pulled in
  }

  void display() {
    background(0);
    textSize(70);
    fill(255, 0, 0);
    text(item, width/2, 3*height/4);
    image(img, width/2, height/4);
  }
}
1 Like

Thanks! This is great. :grinning: Helps me understand what goes in the class and what is outside. Also I like the use of ‘undefined’ to make the conditionals work. Much simpler, and I never would have thought of it.

Is there a way to upload multiple (20+) images all at once into a processing sketch folder?

This is a common question. The answer is yes. If you do it all at once, then it depends on the size of the images and your computer specs as there is so much your computer can handle. The question you need to answer is: do you need to have all those 20 images available at all times?

The best thing to do is for you to try to create a simple code where you attempt to load all the 20 images. If it works in your case, then you can implement it in your project. Otherwise, there will be some brainstorming ahead.

Kf