title: Java mouse picking on diamond tiled map
body: <p>Ok, im at my wits end. I am trying to create a small isometric tile map thats bigger then the screen witha viewpoint i can modify with mouse dragging.
  I got the drawing right (i think), i got the dragging working, just do't seem to be able to get the mouse picking right.
  I have made it so far that i get the tile nearly right, but its off by about half a tiles size and i can't find a way to make up that offset.</p>
  
  <p>Here is the code:</p>
  
  <pre><code>import java.awt.BorderLayout;
  import java.awt.Color;
  import java.awt.Graphics;
  import java.awt.GraphicsConfiguration;
  import java.awt.GraphicsEnvironment;
  import java.awt.Point;
  import java.awt.Polygon;
  import java.awt.Rectangle;
  import java.awt.Transparency;
  import java.awt.event.MouseEvent;
  import java.awt.event.MouseListener;
  import java.awt.event.MouseMotionListener;
  import java.awt.image.BufferedImage;
  import javax.swing.JFrame;
  import javax.swing.JPanel;
  
  public class MapView {
  
      public static void main(String[] args) {
          JFrame test = new JFrame("IsoView");
          test.setSize(800, 600);
          MapViewPane pane = new MapViewPane();
          test.getContentPane().setLayout(new BorderLayout());
          test.getContentPane().add(pane, BorderLayout.CENTER);
          test.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
          test.setVisible(true);
      }
  
      private static class MapViewPane extends JPanel
              implements MouseMotionListener, MouseListener {
  
          private BufferedImage BackImage;
          BufferedImage GrassTile, SelectedBorder;
          private Point MousePoint, PrevView, ViewLocation, Selected;
          private boolean Dragging;
          private int mapwidth, mapheight, tilecount;
  
          public MapViewPane() {
              super();
              this.setOpaque(true);
              createAssets();
              tilecount = 30;
              mapwidth = GrassTile.getWidth() * tilecount;
              mapheight = GrassTile.getHeight() * tilecount;
              ViewLocation = new Point(0, mapheight / 2);
              Selected = new Point(-1, -1);
              addMouseListener(this);
              addMouseMotionListener(this);
          }
  
          private void createAssets() {
              GraphicsConfiguration gc =
                      GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();
              GrassTile = gc.createCompatibleImage(128,
                      64, Transparency.TRANSLUCENT);
              Graphics g = GrassTile.getGraphics();
              Polygon poly = new Polygon();
              poly.addPoint(0, 32);
              poly.addPoint(64, 0);
              poly.addPoint(128, 32);
              poly.addPoint(64, 64);
              g.setColor(Color.GREEN);
              g.fillPolygon(poly);
              g.setColor(Color.BLUE);
              g.drawPolygon(poly);
              g.dispose();
              SelectedBorder = gc.createCompatibleImage(128,
                      64, Transparency.TRANSLUCENT);
              g = SelectedBorder.getGraphics();
              g.setColor(Color.red);
              g.drawPolygon(poly);
              g.dispose();
          }
  
          @Override
          public void paint(Graphics g) {
              //super.paint(g);
              Rectangle visiblerec = this.getVisibleRect();
              g.setColor(Color.BLACK);
              g.fillRect(visiblerec.x, visiblerec.y,
                      visiblerec.width, visiblerec.height);
              checkBackImage();
              Graphics bg = BackImage.getGraphics();
              drawGrassGrid(bg);
              bg.dispose();
              g.drawImage(BackImage, 0, 0, this);
          }
  
          private void drawGrassGrid(Graphics g) {
              int dx = 0;
              int dy = 0;
              g.setColor(Color.BLACK);
              g.fillRect(0, 0, BackImage.getWidth(), BackImage.getHeight());
              for (int x = 0; x &lt; tilecount; x++) {
                  for (int y = 0; y &lt; tilecount; y++) {
                      dx = x * GrassTile.getWidth() / 2
                              - y * GrassTile.getWidth() / 2;
                      dy = x * GrassTile.getHeight() / 2
                              + y * GrassTile.getHeight() / 2;
                      dx -= ViewLocation.x;
                      dy -= ViewLocation.y;
                      g.drawImage(GrassTile, dx, dy, this);
                      if ((x == Selected.x) &amp;&amp; (y == Selected.y)) {
                          g.drawImage(SelectedBorder, dx, dy, this);
                      }
                      g.drawString("(" + x + "," + y + ")", dx, dy
                              + GrassTile.getHeight() / 2);
                  }
              }
          }
  
          private void checkBackImage() {
              if ((BackImage == null) || (BackImage.getWidth() != this.getWidth())
                      || (BackImage.getHeight() != this.getHeight())) {
                  GraphicsConfiguration gc =
                          GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();
                  BackImage = gc.createCompatibleImage(this.getWidth(),
                          this.getHeight(), Transparency.BITMASK);
              }
          }
  
          @Override
          public void mouseDragged(MouseEvent e) {
              if (Dragging) {
                  ViewLocation.x = PrevView.x + MousePoint.x - e.getX();
                  ViewLocation.y = PrevView.y + MousePoint.y - e.getY();
                  if (ViewLocation.x &lt; -mapwidth / 2) {
                      ViewLocation.x = -mapwidth / 2;
                  }
                  if (ViewLocation.y &lt; -mapheight / 2 + this.getHeight()) {
                      ViewLocation.y = -mapheight / 2 + this.getHeight();
                  }
                  if (ViewLocation.x &gt; mapwidth / 2 - this.getWidth()
                          + GrassTile.getWidth()) {
                      ViewLocation.x = mapwidth / 2 - this.getWidth()
                              + GrassTile.getWidth();
                  }
                  if (ViewLocation.y &gt; mapheight / 2 + this.getHeight()) {
                      ViewLocation.y = mapheight / 2 + this.getHeight();
                  }
                  repaint();
              }
          }
  
          @Override
          public void mouseMoved(MouseEvent e) {
          }
  
          @Override
          public void mouseClicked(MouseEvent e) {
              if (!Dragging) {
                  int x = (GrassTile.getWidth() * (e.getY() + ViewLocation.y)
                          + GrassTile.getHeight() * (e.getX() + ViewLocation.x))
                          / (GrassTile.getWidth() * GrassTile.getHeight());
                  int y = (GrassTile.getWidth() * (e.getY() + ViewLocation.y)
                          - GrassTile.getHeight() * (e.getX() + ViewLocation.x))
                          / (GrassTile.getWidth() * GrassTile.getHeight());
  
  //      int x = (int) Math.floor((e.getY() + ViewLocation.y)
  //              / (double) GrassTile.getHeight() - (e.getX() + ViewLocation.x)
  //              / (double) GrassTile.getWidth());
  //      int y = (int) Math.floor((e.getY() + ViewLocation.y)
  //              / (double) GrassTile.getHeight() + (e.getX() + ViewLocation.x)
  //              / (double) GrassTile.getWidth());
  
                  Selected.setLocation(x, y);
                  repaint();
                  System.out.println("(" + x + "," + y + ")");
              }
          }
  
          @Override
          public void mousePressed(MouseEvent e) {
              if ((e.getButton() == MouseEvent.BUTTON1) &amp;&amp; !Dragging) {
                  MousePoint = e.getPoint();
                  PrevView = new Point(ViewLocation);
                  Dragging = true;
              }
          }
  
          @Override
          public void mouseReleased(MouseEvent e) {
              Dragging = false;
              MousePoint = null;
          }
  
          @Override
          public void mouseEntered(MouseEvent e) {
          }
  
          @Override
          public void mouseExited(MouseEvent e) {
          }
      }
  }
  </code></pre>
  
  <p>I have some formulas in the click method commented out wich i tried, but they dont work (x and y axis are inverted that way, havent tried to figure out why yet).
  Would realy appreciate if someone can point me to the mistake i'm making.</p>