Help needed for random change of image on mouse hover/click


#1

Hi!

I’m a student at Anglia Ruskin University’s School of Art (UK) and am working on a piece that I’d like to make interactive. I’ve recently discovered Processing and P5.js and think this could be what I need but am a total noob so really need help!

I’ve developed a set of 16 tiles (.png images) that represent four different pieces of data (so the 16 tiles are four sets of four). I’d like to position these on a 2 x 2 grid (so initially showing a grid of four images) so that when a mouse hovers or clicks on the image it randomly changes to another image. Essentially each image then could change up to four times.

Is this possible? I’ve initially put together the below. I realise it’s totally basic but it was a big step for me :slight_smile:
Any help would be much appreciated and as my project is one involving collaboration if anyone helping would like me to share their details I’d be happy to as part of my final hand showcase/hand in.

Thanks so much, Jess

function setup() {
  createCanvas (1000,1000);
  img1 = loadImage("eatonford1.png");
  img2 = loadImage("eatonford2.png");
  img3 = loadImage("eatonford3.png");
  img4 = loadImage("eatonford4.png");
}

function draw() {
  image(img1, 50,50,400,400);
  image(img2, 400,50,400,400);
  image(img3, 50,400,400,400);
  image(img4, 400,400,400,400);
}

#2

Definitely possible. Looks like you have a great start. First I suggest using an array to keep track of your images this will make this much easier. If arrays are new to you here’s a video explaining them. Here’s an example of how to set up an array of images:

let images = []; // let is similar to var just more modern
// in preload or setup
// use push to add the image on to the end of the list
function preload() {
  images.push(loadImage("eatonford1.png"));
  images.push(loadImage("eatonford2.png"));
  // ... so on and so forth
}

Then you can use four variables to keep track of the indexes of the images you are displaying.

// back at the top of the file before preload
let imageDisplayed0 = 0; // remember array numbering starts at 0
let imageDisplayed1 = 1;
let imageDisplayed2 = 2;
let imageDisplayed3 = 3;

// then in draw access the array with these variables
function draw() {
  image(images[imageDisplayed0], 50,50,400,400);
  image(images[imageDisplayed1], 450,50,400,400); 
  // noticed I changed the location because your images are overlapping
  // don't need to change this but if you want to see the whole image then I suggest doing so
  // it is overlapping because the image method takes (image, x, y, width, height)
  // ... continue on
}

Last you’ll need to use the mouseClicked() function and check to see if the mouse is inside of the image using mouseX and mouseY, which are built in variables. If you’re not farmilar with if statements I suggest watching this video.

function mouseClicked() {
  if (mouseX > 50 && mouseX < 450 && mouseY > 50 && mouseY < 450) {
    if (imageDisplayed0 < 15)  { // 15 is the number of elements in your array minus one
      imageDisplayed0 += 4;
      // above is the same as imageToUse0 = imageToUse + 4;
    }
  }
  // do the same for the 3 other images
}

Note: If you post code in the future please auto format your code (shift + tab in p5.js web editor) and then paste it between ``` ```. This makes it much easier to read.


#3

Thanks so much - I really appreciate the quick response and help - I’ll have a go then at the above, watch the video and see what happens :smile: Jess


#4

Hi @figraham,

Thanks again for your help on this. I’m a bit stuck! I think I’ve followed what you’ve said but I seem to get a ‘Script error. (: line 0)’ when trying to run the code. Here is what I’ve done:

\\\
let images[];

let imageDisplayed0 = 0;
let imageDisplayed1 = 1;
let imageDisplayed2 = 2;
let imageDisplayed3 = 3;

function preload() {
  images.push(loadImage("eatonford1.png"));
  images.push(loadImage("eatonford2.png"));
  images.push(loadImage("eatonford3.png"));
  images.push(loadImage("eatonford4.png"));
  images.push(loadImage("eatonsocon1.png"));
  images.push(loadImage("eatonsocon2.png"));
  images.push(loadImage("eatonsocon3.png"));
  images.push(loadImage("eatonsocon4.png"));
  images.push(loadImage("eynesbury1.png"));
  images.push(loadImage("eynesbury2.png"));
  images.push(loadImage("eynesbury3.png"));
  images.push(loadImage("eynesbury4.png"));
  images.push(loadImage("priorypark1.png"));
  images.push(loadImage("priorypark2.png"));
  images.push(loadImage("priorypark3.png"));
  images.push(loadImage("priorypark4.png"));
}

function setup() {
  createCanvas(1000, 1000);
}

function draw() {
  image(images[imageDisplayed0], 50, 50, 400, 400);
  image(images[imageDisplayed1], 500, 50, 400, 400);
  image(images[imageDisplayed2], 50, 500, 400, 400);
  image(images[imageDisplayed3], 500, 500, 400, 400);
}

function mouseClicked() {
  if (mouseX > 50 && mouseX < 450 && mouseY > 50 && mouseY < 450) {
    if (imageDisplayed0 < 15)
      imageDisplayed0 += 4;
  }
}

function mouseClicked() {
  if (mouseX > 500 && mouseX < 900 && mouseY > 50 && mouseY < 450) {
    if (imageDisplayed0 < 15)
      imageDisplayed0 += 4;
  }
}

function mouseClicked() {
  if (mouseX > 50 && mouseX < 450 && mouseY > 500 && mouseY < 900) {
    if (imageDisplayed0 < 15)
      imageDisplayed0 += 4;
  }
}

function mouseClicked() {
  if (mouseX > 500 && mouseX < 900 && mouseY > 500 && mouseY < 900) {
    if (imageDisplayed0 < 15)
      imageDisplayed0 += 4;
  }
}
\\\

TIA :slight_smile:

Jess


#5

Line 0? I guess that is because of the \ that your code starts with - it’s not needed and is not understood by the computer.

Also, you seem to be defining the same mouseClicked() function multiple times - as far as I’m aware, in Javascript, defining a function that already exists overwrites it, so only the last mouseClicked() will work. That or it gives an error about it, which is probably the very reason of this error.

I suggest putting all the if(... statements and everything they contain into a single mouseClicked() function, like this:

function mouseClicked() {
  if (mouseX > 50 && mouseX < 450 && mouseY > 50 && mouseY < 450) {
    if (imageDisplayed0 < 15)
      imageDisplayed0 += 4;
  }
  if (mouseX > 500 && mouseX < 900 && mouseY > 50 && mouseY < 450) {
    if (imageDisplayed0 < 15)
      imageDisplayed0 += 4;
  }
  if (mouseX > 50 && mouseX < 450 && mouseY > 500 && mouseY < 900) {
    if (imageDisplayed0 < 15)
      imageDisplayed0 += 4;
  }
  if (mouseX > 500 && mouseX < 900 && mouseY > 500 && mouseY < 900) {
    if (imageDisplayed0 < 15)
      imageDisplayed0 += 4;
  }
}

P.S. When writing a post here, please select your code and use a button above the text box that looks like </> - it formats the code into a colorful text with monospace font like above, making it easier to read.


#6

Thanks for the quick response :slight_smile: Please ignore the ‘/’ marks - I was trying to distinguish the code from my message text but clearly didn’t do it very well! So not exactly sure why the error message is appearing. When running it in Chrome the console message reads ‘Uncaught SyntaxError: Unexpected token [ (sketch: line 1)’.

Thanks for the mouseclicked advice - I’ve updated that so the code now reads

let images[];

let imageDisplayed0 = 0;
let imageDisplayed1 = 1;
let imageDisplayed2 = 2;
let imageDisplayed3 = 3;

function preload() {
  images.push(loadImage("eatonford1.png"));
  images.push(loadImage("eatonford2.png"));
  images.push(loadImage("eatonford3.png"));
  images.push(loadImage("eatonford4.png"));
  images.push(loadImage("eatonsocon1.png"));
  images.push(loadImage("eatonsocon2.png"));
  images.push(loadImage("eatonsocon3.png"));
  images.push(loadImage("eatonsocon4.png"));
  images.push(loadImage("eynesbury1.png"));
  images.push(loadImage("eynesbury2.png"));
  images.push(loadImage("eynesbury3.png"));
  images.push(loadImage("eynesbury4.png"));
  images.push(loadImage("priorypark1.png"));
  images.push(loadImage("priorypark2.png"));
  images.push(loadImage("priorypark3.png"));
  images.push(loadImage("priorypark4.png"));
}

function setup() {
  createCanvas(1000, 1000);
}

function draw() {
  image(images[imageDisplayed0], 50, 50, 400, 400);
  image(images[imageDisplayed1], 500, 50, 400, 400);
  image(images[imageDisplayed2], 50, 500, 400, 400);
  image(images[imageDisplayed3], 500, 500, 400, 400);
}

function mouseClicked() {
  if (mouseX > 50 && mouseX < 450 && mouseY > 50 && mouseY < 450) {
    if (imageDisplayed0 < 15)
      imageDisplayed0 += 4;
  }
  if (mouseX > 500 && mouseX < 900 && mouseY > 50 && mouseY < 450) {
    if (imageDisplayed0 < 15)
      imageDisplayed0 += 4;
  }
  if (mouseX > 50 && mouseX < 450 && mouseY > 500 && mouseY < 900) {
    if (imageDisplayed0 < 15)
      imageDisplayed0 += 4;
  }
  if (mouseX > 500 && mouseX < 900 && mouseY > 500 && mouseY < 900) {
    if (imageDisplayed0 < 15)
      imageDisplayed0 += 4;
  }
}


#7

Try let images = [];


#8

Thank you - that has worked in terms of loading the first images. I now have a problem I’m not sure how to resolve. The only mouse clicked event that works is the last one. When I click on the image to the bottom right of the canvas the image changes (up to four times) but they appear over the top of each other (the previous ones don’t disappear) and unfortunately the other mouseclicked events don’t seem to work. Again, any help much appreciated :grinning:

let images = [];
 
let imageDisplayed0 = 0;
let imageDisplayed1 = 1;
let imageDisplayed2 = 2;
let imageDisplayed3 = 3;

function preload() {
  images.push(loadImage("eatonsocon1.png"));
  images.push(loadImage("eatonsocon2.png"));
  images.push(loadImage("eatonsocon3.png"));
  images.push(loadImage("eatonsocon4.png"));
  images.push(loadImage("eatonford1.png"));
  images.push(loadImage("eatonford2.png"));
  images.push(loadImage("eatonford3.png"));
  images.push(loadImage("eatonford4.png"));
  images.push(loadImage("eynesbury1.png"));
  images.push(loadImage("eynesbury2.png"));
  images.push(loadImage("eynesbury3.png"));
  images.push(loadImage("eynesbury4.png"));
  images.push(loadImage("priorypark1.png"));
  images.push(loadImage("priorypark2.png"));
  images.push(loadImage("priorypark3.png"));
  images.push(loadImage("priorypark4.png"));
}

function setup() {
  createCanvas (900,900);
}

function draw() {
  image(images[imageDisplayed0], 50,50,400,400);
  image(images[imageDisplayed1], 500,50,400,400);
  image(images[imageDisplayed2], 50,500,400,400);
  image(images[imageDisplayed3], 500,500,400,400);
}

function mouseClicked() {
  if (mouseX > 50 && mouseX < 450 && mouseY > 50 && mouseY < 450) {
    if (imageDisplayed0 < 15)  
      imageDisplayed0 += 4;
    }
  }
function mouseClicked() {
  if (mouseX > 500 && mouseX < 900 && mouseY > 50 && mouseY < 450) {
    if (imageDisplayed1 < 15)  
      imageDisplayed1 += 4;
    }
  }
function mouseClicked() {
  if (mouseX > 50 && mouseX < 450 && mouseY > 500 && mouseY < 900) {
    if (imageDisplayed2 < 15)  
      imageDisplayed2 += 4;
    }
  }
function mouseClicked() {
  if (mouseX > 500 && mouseX < 900 && mouseY > 500 && mouseY < 900) {
    if (imageDisplayed3 < 15)  
      imageDisplayed3 += 4;
    }

}

#9

Looks like you have a couple syntax errors. JavaScript doesn’t work well if you have multiple functions with the same name. So you should put the if statements into one function.

Also you have some inconsistent curly brackets. It looks like the inner if statements don’t get opened. Make sure you use one of the following formats:

// One line shorted if statement
// This form works only if there's one line inside of the if statement
// Can reduce code length but can also be confusing at times
if (something is true)
  then do this;

// Normal 
if (something is true) {
  then do this;
}

I have to apologize I may have misunderstood your goal. I’m still not entirely sure what you want so here are a couple options:

// All other code looks fine except if using option 3 change the variables to this.
// You don't need to change this part if you are using any of the other options
let imageDisplayed0 = 0;
let imageDisplayed1 = 4;
let imageDisplayed2 = 8;
let imageDisplayed3 = 12;

function mouseClicked() {
  if (mouseX > 50 && mouseX < 450 && mouseY > 50 && mouseY < 450) {
    // Option 1: Current solution but with cycling
    if (imageDisplayed0 + 4 <= 15) { // example of incriminating through a set of four images
      imageDisplayed0 += 4;
    } else { // can add else to get it to restart at the beginning
      imageDisplayed0 = 0; // use the value that you used at the start
    }
  }
  if (mouseX > 500 && mouseX < 900 && mouseY > 50 && mouseY < 450) {
    // Option 2: Selects an image at random
    // may lead to the same image on the screen twice
    imageDisplayed1 = floor(random(image.length));
  }
  if (mouseX > 50 && mouseX < 450 && mouseY > 500 && mouseY < 900) {
    // Option 3: Selects random out of 4 images
    // you may have to rearrange the order of your images
    imageDisplayed2 = 8;
    imageDisplayed2 += floor(random(4));
  }
  if (mouseX > 500 && mouseX < 900 && mouseY > 500 && mouseY < 900) {
    // Option 4 : Current Setup
    if (imageDisplayed3 + 4 <= 15) {
      imageDisplayed3 += 4;
    }
  }
}

As for your concern the images don’t disappear. The only way to get rid of images you’ve already drawn on the canvas is to cover them up. The most common way to do this is to use background() which will basically fill the entire canvas with a color and cover up everything that has already been drawn. Try adding this as the first line of draw:

background(255);

Hopefully that helps. Feel free to ask me to clarify not sure if everything makes sense.


#10

My reply above applies to that problem of yours! You are defining mouseClicked() function multiple times, so only the last definition that has that single if statement is “written” to it and not any other.