Struggling to find cause of mouseX shifting to the right when used

I’m currently trying to make a program that shows a grid of tiles that change color when clicked. I’ve made it so that the tiles are evenly distributed with an edge or gutter around the sides no matter the number of tiles or size of the window. It looks like the image attached.

The problem arises when I try to perform the clicking action on the tiles. I have mouseClicked() call a function inside every tile, passing the mouseX and mouseY position (I have no issues with the y position) in to determine if that tiles column has been clicked, turning those tiles green if it has been clicked. The issue is that when clicking, the column exactly to the RIGHT of the one clicked is the one that turns green. Here’s what it looks like if I click the second left most column:

Another strange but I’m assuming telling part of the issue i’m having is that if I click the column on the farthest right side, the tiles on the farthest left side turn green, almost as if my click warped through the wall and back to the other side like in pacman.

When having the program print out my mouseX position and the clicked columns boundaries, it tells me that the mouseX coordinate was indeed where it should of been, yet the column to the right of that one is the one that turns green. This is the code in my Tile class that checks if the mouse was in that column when it is called:

public void flipped(float clickX, float clickY){
        if(clickX > x && clickX < x+width){// && clickY > y && clickY < y + height){
            flipped = !flipped;
            //System.out.println("Click X: " + clickX + "   Left edge: " + x + "  Right edge: " + (int)(width+x));
        }
    }

Here’s the code inside the Tiles class (the class that creates an object to hold all the tiles and instantiate them) that fills the array with tiles in the correct position:

public void initTiles(){
        float x;
        float y;
        //For every column,...
        for(int c = 0; c < tilePerCol; ++c) {
            //y is one gutter height apart from the last tile
            y = c * (tileHeight+gutterHeight) + gutterHeight;
            //for every row...
            for(int r = 0; r < tilePerRow; ++r){
                //x is one gutter width from the last tile, starting at 0 for each row in a column
                x = r*(gutterWidth+tileWidth) + gutterWidth;
                tiles.add(new Tile(p, tileWidth, tileHeight, x, y));
            }
        }
       // System.out.println(tiles.size());
    }

I have tried subtracting the width from where I check the tile click detection, which works for everything except the farthest left column, which cannot be interacted with using that fix.
I have also tried messing with collision boundaries which showed itself to not be the problem.

I’m not sure how this is happening, because the click detection is handled by each tile individually, so the issue isn’t as simple as that it’s starting at the wrong index.

I would appreciate any advice, i’m spent on trying to figure out what is going on here, as I’m sure it’s glaringly obvious.
Thanks,

1 Like

This is wrong

You don’t want width you want tileWidth

1 Like

Thanks for the suggestion.

tileWidth is calculated at the start of the program inside a Tiles object and passed into each individual Tile. So the width of a tile and tileWidth is always the same, the difference being in where the value is stored.

I’m still not sure why this only happens on the x, but not the y, and i’m even more confused why it is shifted perfectly to the right and even wraps back to the first column if you click the last.

Hi @falseStart,

It is quite hard to help you without a MCVE test your issue on our own.

That beeing said, it seems that the y and x value of your tiles are reversed. I would write this:

public void initTiles() {
  float x;
  float y;
  
  //For every column,...
  for (int c = 0; c < tilePerCol; ++c) {
    x = c * (gutterWidth+tileWidth) + gutterWidth;
    
    //for every row...
    for (int r = 0; r < tilePerRow; ++r) {
      y = r * (tileHeight+gutterHeight) + gutterHeight;
      tiles.add(new Tile(p, tileWidth, tileHeight, x, y));
    }
  }
}

But again, without having some more context, hard to say…

Thanks @jb4x,

I don’t post on forums a lot, so I appreciate the info. Here’s an MCVE with just the bits to reproduce the issue (Done in processing 3.5.4):

This is a condensed version of the code containing the Tile and Tiles classes with just the tile related functions:

import java.util.ArrayList;

Tiles tiles;

public void settings(){
  size(1000,1000);
}

public void setup(){
  background(255);
  tiles = new Tiles(10);
}

public void draw(){
  tiles.draw();
}

public void mouseClicked(){
  tiles.flipped(mouseX);
}

/*

Tile Class:

*/

public class Tile {
  private float width;
  private float height;
  private float x;
  private float y;
  private boolean flipped;
  
  public Tile(float width, float height, float x, float y){
    this.width = width;
    this.height = height;
    this.x = x;
    this.y = y;
    flipped = false;
  }
  
  public void draw(){
    rect(x,y,width,height);
    if(flipped){
      fill(0,225,20);
    }
    if(!flipped){
      fill(255);
    }
  }
  
  public void flipped(float clickX){
    if(clickX > x && clickX < x+width){
      flipped = !flipped;
    }
  }

}

/*

Tiles Class:

*/

public class Tiles {
  private int tilePerRow;
  private int tilePerCol;
  private float tileWidth;
  private float gutterWidth;
  private float tileHeight;
  private float gutterHeight;
  private ArrayList<Tile> tiles;

  public Tiles(int tilePerRow){
    this.tilePerRow = tilePerRow;
    tilePerCol = tilePerRow;
    tiles = new ArrayList<Tile>();
    initTileSize(width,height);
    initTiles();
  }

  public void initTileSize(int width, int height){
    //Width of tiles:
    gutterWidth = (width/tilePerRow)/10;
    tileWidth = ((width-gutterWidth)/tilePerRow) - (gutterWidth);
    //Height of tiles:
    gutterHeight = (height/tilePerRow)/10;
    tileHeight = ((height-gutterHeight)/tilePerRow) - gutterHeight;
  }

  public void initTiles(){
    float x;
    float y;
    for(int c = 0; c < tilePerCol; ++c) {
      y = c * (tileHeight+gutterHeight) + gutterHeight;
      for(int r = 0; r < tilePerRow; ++r){
        x = r*(gutterWidth+tileWidth) + gutterWidth;
        tiles.add(new Tile(tileWidth, tileHeight, x, y));
      }
    }
  }

  public void flipped(float clickX){
    for(Tile tile : tiles){
      tile.flipped(clickX);
    }
  }

  public void draw(){
    for(Tile tile : tiles){
      tile.draw();
    }
  }
}

I tried flipping the x and y as suggested, and it behaved the same other than making the top tile now shifted to the left once.

I’m still not entirely sure where the problem resides, but I don’t think it has to do with the initTiles function, because changing that code and creating tiles manually creates the same results; the tiles to the left are the ones that turn green.

1 Like

Thank you for the code.

You made a silly mistake in the draw function of your Tile class. rect(x,y,width,height); should be after your condition where you set your colors.

3 Likes

I didn’t even think to look there, but I definitely should have. Appreciate the help!

Happy to help :relaxed:

I also noticed that your were using width and height variables in your Tile class. It can be confusing as they are already keyword of processing for the height and width of the canvas. It might be a good option to rename them h and w for example.

The x and y coordinate were correct the way you were writing them by the way. But be careful to use proper variables to compute the height of your tiles. It should be tilePerCol and not tilePerWidth.

I edited and commented your code with everything I wrote above:

import java.util.ArrayList;

Tiles tiles;

public void settings(){
  size(1000,1000);
}

public void setup(){
  background(255);
  tiles = new Tiles(10, 5);
}

public void draw(){
  tiles.draw();
}

public void mouseClicked(){
  tiles.flipped(mouseX);
}

/*

Tile Class:

*/

public class Tile {
  private float w;  // *** Better use w & h to differenciate from width and height
  private float h;  // *** Better use w & h to differenciate from width and height
  private float x;
  private float y;
  private boolean flipped;
  
  public Tile(float w, float h, float x, float y){
    this.w = w;
    this.h = h;
    this.x = x;
    this.y = y;
    flipped = false;
  }
  
  public void draw(){
    if(flipped){
      fill(0,225,20);
    }
    if(!flipped){
      fill(255);
    }
    rect(x,y,w,h); // *** This line need to be after you set up your color
  }
  
  public void flipped(float clickX){
    if(clickX > x && clickX < x + w){
      flipped = !flipped;
    }
  }

}

/*

Tiles Class:

*/

public class Tiles {
  private int tilePerRow;
  private int tilePerCol;
  private float tileWidth;
  private float gutterWidth;
  private float tileHeight;
  private float gutterHeight;
  private ArrayList<Tile> tiles;

  public Tiles(int tilePerRow, int tilePerCol){
    this.tilePerRow = tilePerRow;
    this.tilePerCol = tilePerCol;   // *** Nb of column <> Nb of row for test purpose
    tiles = new ArrayList<Tile>();
    initTileSize(width, height);
    initTiles();
  }

  public void initTileSize(int w, int h){
    //Width of tiles:
    gutterWidth = (w/tilePerRow)/10; 
    tileWidth = ((w-gutterWidth)/tilePerRow) - (gutterWidth); 
    
    //Height of tiles:
    gutterHeight = (h/tilePerCol)/10;                            // *** Should be tilePerCol
    tileHeight = ((h-gutterHeight)/tilePerCol) - gutterHeight;   // *** Should be tilePerCol
  }

  public void initTiles(){
    float x;
    float y;
    for(int c = 0; c < tilePerCol; ++c) {
      y = c * (tileHeight+gutterHeight) + gutterHeight;
      
      for(int r = 0; r < tilePerRow; ++r){
        x = r * (gutterWidth+tileWidth) + gutterWidth;
        tiles.add(new Tile(tileWidth, tileHeight, x, y));
      }
    }
  }

  public void flipped(float clickX){
    for(Tile tile : tiles){
      tile.flipped(clickX);
    }
  }

  public void draw(){
    for(Tile tile : tiles){
      tile.draw();
    }
  }
}
4 Likes