Detecting when the mouse is over an object

Hi all,

I hope this isn't a duplicate but I haven't found a thread that told me what I wanted to know.

To keep it short, I'm trying to make a little "Pairs" style game and now I'm looking for a way to detect when the mouse is hovering over one of the cards. I have written some code, shown below, that initializes an array, then populates it with the specified number of Objects from the "Card" class and displays them.

If possible, I'd like to be able to trigger a function (change color or something like that) when hovering over the card; if that doesn't work, only triggering something when actually clicking the card would be fine as well.

The only idea I had was to iterate over the array on every MousePressed(), calculate the size of each rect (x and y are stored in the object, width and height are global variables) and compare if MouseX and MouseY are between the rects or not, but that seems really overengineered and it would probably be really slow.

Is there a better way?

Thank you very much!

Card[] cards = new Card [36];

int rows = 6;
int columns = 6;
int cardsize = 75;
int space = 25;
int border = 12;
int cardstotal = (rows * columns);



void setup() {
  size(600, 600);
  background(255, 204, 0);
  int cardsinrow = 0;
  int cardsincolumn = 0;

  // Puts cards where they belong
  for (int i = 0; i < cards.length; i++) {
    cards[i] = new Card((border + (cardsinrow * (cardsize + space))), (border + (cardsincolumn * (cardsize + space))), 1, false);
    cardsinrow++;
    if (cardsinrow >= columns) { // "Line break" for the cards
      cardsinrow = 0;
      cardsincolumn++;
    }
    println(cardsincolumn); // Debug
  }
}

void draw() {

  for (int i=0; i < cards.length; i++) {
    cards[i].display();
  }
}

public class Card {

  int cardposx;
  int cardposy;
  int cardcontent;
  boolean cardstatus;


  Card(int cardposx_, int cardposy_, int cardcontent_, boolean cardstatus_) {
    cardposx = cardposx_;
    cardposy = cardposy_;
    cardcontent = cardcontent_;
    cardstatus = cardstatus_;
  }

  void display() {
    rect(cardposx, cardposy, cardsize, cardsize);
  }
}

// class =======================================================

Answers

  • Thank you, but that doesn't solve my problem, sorry if I wasn't clear enough. Detecting if the mouse is over a rect() seems doable for me, but not if there's 36 of them and their coordinates are not stored in variables, but in objects.

  • Card[] cards = new Card [36];
    
    int rows = 6;
    int columns = 6;
    int cardsize = 75;
    int space = 25;
    int border = 12;
    int cardstotal = (rows * columns);
    boolean pMousePressed;
    
    
    void setup() {
      size(600, 600);
      int cardsinrow = 0;
      int cardsincolumn = 0;
    
      // Puts cards where they belong
      for (int i = 0; i < cards.length; i++) {
        cards[i] = new Card((border + (cardsinrow * (cardsize + space))), (border + (cardsincolumn * (cardsize + space))), 1, false);
        cardsinrow++;
        if (cardsinrow >= columns) { // "Line break" for the cards
          cardsinrow = 0;
          cardsincolumn++;
        }
        println(cardsincolumn); // Debug
      }
    }
    
    void draw() {
     background(255, 204, 0);
      for (int i=0; i < cards.length; i++) {
        cards[i].display();
      }
      pMousePressed=mousePressed;
    }
    
    public class Card {
    
      int cardposx;
      int cardposy;
      int cardcontent;
      boolean cardstatus;
      boolean mouseover;
      boolean dragged;
    
    
      Card(int cardposx_, int cardposy_, int cardcontent_, boolean cardstatus_) {
        cardposx = cardposx_;
        cardposy = cardposy_;
        cardcontent = cardcontent_;
        cardstatus = cardstatus_;
      }
    
      void display() {
        mouseover=cardposx<=mouseX&&mouseX<=cardposx+cardsize&&
                  cardposy<=mouseY&&mouseY<=cardposy+cardsize;
        if(mouseover && mousePressed && !pMousePressed){dragged=true;}
        if(!mousePressed){dragged=false;}
    
        if(dragged){cardposx+=mouseX-pmouseX;
                    cardposy+=mouseY-pmouseY;}
        rect(cardposx, cardposy, cardsize, cardsize);
      }
    }
    
  • If your cards are in a grid (i haven't run the code but it looks that way) then dividing the mouse x by the width of the card will give you the grid x. Ditto for mouse y / card height. Is that enough?

  • It's a bit more complicated with a border and spacing but...

  • koog's suggestion is probably most useful for you

    Card[] cards = new Card [36];
    int rows = 6;
    int columns = 6;
    int cardsize = 75;
    int space = 25;
    int border = 12;
    int cardstotal = (rows * columns);
    void setup() {
      size(600, 600);
      int cardsinrow = 0;
      int cardsincolumn = 0;
      // Puts cards where they belong
      for (int i = 0; i < cards.length; i++) {
        cards[i] = new Card((border + (cardsinrow * (cardsize + space))), (border + (cardsincolumn * (cardsize + space))), 1, false);
        cardsinrow++;
        if (cardsinrow >= columns) { // "Line break" for the cards
          cardsinrow = 0;
          cardsincolumn++;
        }
        println(cardsincolumn); // Debug
      }
    }
    void draw() {
     background(255, 204, 0);
      for (int i=0; i < cards.length; i++) {
        cards[i].display();
      }
    }
    void mouseClicked(){
      int len,lenx,leny,select=-1;
      len=(cardsize+space);
      lenx=mouseX/len;
      leny=mouseY/len;
      if(space<=mouseX%len&&mouseX%len<=len-space&&
         space<=mouseY%len&&mouseY%len<=len-space
     ){select=lenx+leny*rows;}
     println(select); 
    }
    public class Card {
    
      int cardposx;
      int cardposy;
      int cardcontent;
      boolean cardstatus;
      Card(int cardposx_, int cardposy_, int cardcontent_, boolean cardstatus_) {
        cardposx = cardposx_;
        cardposy = cardposy_;
        cardcontent = cardcontent_;
        cardstatus = cardstatus_;
      }
      void display() {
        rect(cardposx, cardposy, cardsize, cardsize);
      }
    }
    
  • edited July 2017 Answer ✓

    @howaboutno -- Re:

    Detecting if the mouse is over a rect() seems doable for me, but not if there's 36 of them and their coordinates are not stored in variables, but in objects.

    A general approach to collision detection for lists of objects is, instead of:

    collide(mouseX,mouseY);
    

    ...just make collision a method of your class, and then loop through your object list:

    for (int i = 0; i < objectlist.length; i++){
       objectlist[i].collide(mouseX,mouseY);
    }
    

    So the collision code is the same -- you just put it in your class.

  • @jeremydouglass

    This is a really clean solution and it works perfectly, thank you!

    In case someone cares how exactly I did it (yeah I'm looking at you, person who just found this thread via Google three years from now), here's the code:

    Card[] cards = new Card [36];
    
    int rows = 6;
    int columns = 6;
    int cardsize = 75;
    int space = 25;
    int border = 12;
    int cardstotal = (rows * columns);
    
    
    
    void setup() {
      size(600, 600);
      background(255, 204, 0);
      int cardsinrow = 0;
      int cardsincolumn = 0;
    
      // Puts cards where they belong
      for (int i = 0; i < cards.length; i++) {
        cards[i] = new Card((border + (cardsinrow * (cardsize + space))), (border + (cardsincolumn * (cardsize + space))), 1, false);
        cardsinrow++;
        if (cardsinrow >= columns) { // "Line break" for the cards
          cardsinrow = 0;
          cardsincolumn++;
        }
        println(cardsincolumn); // Debug
      }
    }
    
    void draw() {  
    
      for (int i=0; i < cards.length; i++) {
        cards[i].display();
      }
    
      if (mousePressed) {
        for (int i = 0; i < cards.length; i++) {
          if (cards[i].collision(mouseX, mouseY)) {
            cards[i].cardstatus = true;
          }
        }
      }
    }
    
    
    
    
    public class Card {
    
      int cardposx;
      int cardposy;
      int cardcontent;
      boolean cardstatus;
    
    
      Card(int cardposx_, int cardposy_, int cardcontent_, boolean cardstatus_) {
        cardposx = cardposx_;
        cardposy = cardposy_;
        cardcontent = cardcontent_;
        cardstatus = cardstatus_;
      }
    
      void display() {
        if (cardstatus) {
          fill(0,200,200);
        }
        rect(cardposx, cardposy, cardsize, cardsize);
        fill(255);
      }
    
      boolean collision(float mouseX, float mouseY) {
        if (mouseX >= cardposx &&         // right of the left edge AND
          mouseX <= cardposx + cardsize &&    // left of the right edge AND
          mouseY >= cardposy &&         // below the top AND
          mouseY <= cardposy + cardsize) {    // above the bottom
          return true;
        }
        return false;
      }
    }
    
    // class =======================================================
    
  • Oh, and of course thank you to @prince_polka and koogs, too! As you can see, I've incorporated bits and pieces of your ideas in the code :)

  • Hello howaboutno

    I am the guy who found this code sample. Your post does not show what is the year of your post. It is August 2017 so......

  • @budski82 -- hover over any post date in the forum with your mouse, and it will pop-up a box showing the full date, time, and year.

Sign In or Register to comment.