• 0

[VB.NET] Detect click on Isometric Grid


Question

I have an Isometric grid that gets drawn to a bitmap bigger then the screen, then the section of it that has been scrolled to is drawn. How can I figure out where on the grid the user clicked? Should I create an invisible normal square grid over the isometric one? It wouldn't perfect but it might work. One thing that makes it harder is the physical size of the part drawn on screen is smaller then the overall grid size so some offsetting of the coords of whatever was clicked will need to be done.

Link to comment
Share on other sites

15 answers to this question

Recommended Posts

  • 0
I don't think this can be done. Determining the ROW is easy. As for the specific column, I have never seen it done.

Well, I kind of figured it out. I overlayed an invisible square grid over it which sort of works, although it isn't as accurate as I would like.

Link to comment
Share on other sites

  • 0
Well, I kind of figured it out. I overlayed an invisible square grid over it which sort of works, although it isn't as accurate as I would like.

You stated the grid is larger than the screen. So, are you scrolling the overlay in sync with the grid? That's defiantly an interesting solution you've come up with.

Link to comment
Share on other sites

  • 0

I think the most obvious correct solution is through mathematics. Basically, the grid should internally be represented as a map of squares in cartesian coordinates. Now if you want an isometrical representation, all you need to do is rotate the coordinates by (pi/4). Simply multiply each coordinate by the corresponding rotation matrix. Then if you need to translate and scale it for your screen, create the corresponding translation and scaling matrices too, and apply them in order.

Screen coordinate = map coordinate * rotation matrix * translation matrix * scaling matrix

There are two benefits to this approach. First, working internally with squares in cartesian coordinates is very easy and requires minimal calculations. Secondly, once you have the matrices for each transformation, it is trivial to get the inverse transformations, therefore solving the problem of transforming a screen coordinate into a map coordinate. If you have the math to transform a map coordinate into a screen coordinate, inverse the equation and you solve the inverse problem.

If you need a primer on linear transformations, see http://en.wikipedia.org/wiki/Transformation_matrix

Edited by Dr_Asik
Link to comment
Share on other sites

  • 0

My head felt fine earlier. It hurts now.

Anyway, thanks for the help, I'll check that page and try and see if I can figure this out, since your way sounds like it would work. And the overlayed grid isn't literally there, I simply get the mouse position and divide by half of the size of a grid-square.

Link to comment
Share on other sites

  • 0

A word of warning, if you haven't done any linear algebra, this could be a steep learning curve. Also, I don't think Visual Basic or .NET has any matrix library so you'd need to either roll up your own, or use an existing one. When you work with a proper game framework like DirectX or XNA, that is provided. :) If you install XNA I think that from VB.NET you are able to reference the microsoft.xna.framework assembly, which contains a fully-fledged Matrix class, so maybe you can use it in your application. There's a blog explaining the procedure here.

Link to comment
Share on other sites

  • 0
Yeah, i've used XNA in Vb.net before, but linear algebra is new to me.
Well then at least the Matrix class hides most of the gory details to you, so I think you could do it. If you have any questions feel free to ask.
Link to comment
Share on other sites

  • 0

I understand the basis of what you mean, and I think I can do it... but.. uh I don't how to start...

Create a matrix object and... uh...

Can you point me in the right direction and then I'll figure it out myself?

Link to comment
Share on other sites

  • 0

I don't know what you're currently using to represent your grid, but let's say you've got a two-dimensional array of (x, y) coordinates representing the upper-left corner of each square. All your game logic can just use that, see the board as strictly vertical/horizontal, no tilting, just squares.

Now when you get to actually draw that grid on the screen, now you want to transform your logical map coordinates into screen coordinates. Since you're going to use XNA you should store your points as Vector3s, use only the X and Y since it's 2D, the Z stays at 0 for all points.

The first transformation is to rotate the map by (pi/4). Now notice that sin(pi/4) and cos(pi/4) are both equal to sqrt(2)/2.

So, let k = sqrt(2)/2, your rotation Matrix is

k -k  0
k  k  0
0  0  0

You can just trust me on that (you shouldn't, it's 0:15 here and my mind's getting fuzzy) or check Rotation Matrix on wikipedia, it's simple.

Now your rotated coordinates are simply

Vector3 rotated = Vector3.Transform(original, rotation);

where original is your original pair of coordinates (another Vector3), and rotation is the matrix.

For translation you just add a vector to each coordinate, and for scaling you multiply them by a scalar (a single constant - not a vector). I'm not sure if you should do translation first and then scaling or the opposite. In any case, I'm pretty sure rotation comes first. Order matters in linear transformations, i.e., rotation * translation != translation * rotation. It would be nice if you could easily test different transformations and visually see the result, as sometimes you can have surprises. For instance, the rotation matrix here is centered on 0, 0; if that is the upper-left corner of your grid, that will rotate it around that corner. It's fine, you just have to be aware of it.

Once you have that, you have your game-to-screen equation, and based on that you can find the screen-to-game equation.

Edited by Dr_Asik
Link to comment
Share on other sites

  • 0

Interesting! It's a 2D level editor for Portal maps? How does that work, since Portal is a 3D game?

As a side thought, if you're going to use the xna.framework assembly, you'll need to ship that with your game somehow or require that it's installed on the target system, since it's not part of .NET. Just rambling now, I think I need some sleep too. :)

Link to comment
Share on other sites

  • 0

Sorry to bump, but I got some more of this figured out. I didn't do exactly what you said, but from what you shared, I think I found a simpler way to do it. I'm using the Transform command with a X and Y matrix created with the CreateRotationMatrix with the rotation set to a 45 degree angle. It seems to work but there is one problem. The X works fine but the Y isn't always quite right. Sometimes its off by 1.5-0.5. Should I divide Y by less when calculating the size in grid squares?

Also, I referenced only the main XNA DLL, can I just copy that with the program or does the user still need the full XNA?

Link to comment
Share on other sites

  • 0

Not sure about either of your questions, sorry. Nice find on CreateRotationMatrix, in theory it should do exactly what I explained, except you just input the angle instead of calculating each value.

My guess on the Ys being off is that you expect your isometrical tiles to be wider than tall. However if you use a square map and just rotate it, this will keep the same proportions, that is, tiles will be as wide as tall. You need to add a transformation that squeezes the map a bit along the Y-axis, after the rotation. You can represent it as a constant between 1 and 0 which you multiply with every y coordinate, or, as a matrix :

1 0 0
0 k 0
0 0 0

The advantage to matrix representation is that finding the inverse transformation is as simple as calling the method Invert.

I suppose you would just need to re-distribute the XNA framework dll, but I'm not sure if that's ok in regards to the XNA license. In doubt, drop a question on the forums at creators.xna.com.

Link to comment
Share on other sites

This topic is now closed to further replies.
  • Recently Browsing   0 members

    • No registered users viewing this page.