This week's book giveaway is in the OO, Patterns, UML and Refactoring forum. We're giving away four copies of Refactoring for Software Design Smells: Managing Technical Debt and have Girish Suryanarayana, Ganesh Samarthyam & Tushar Sharma on-line! See this thread for details.
Hello, I'm working on an isometric-style chess game (I've already completed a 2D one), and I'm having a bit of trouble detecting which tile the mouse is in. Obviously, I cannot use regular rectangles which use the image's boundaries, because there would be much overlapping. I have looked into using Areas, but I am uncertain if that is the correct solution. The only other method I can think of (besides resorting to collision-detection algorithms) is if I could somehow transform a rectangle to fit the boundaries (rotating possibly). Any help is greatly appreciated. -Karl Nilsson
Well, let's see. If you're drawing this in a classic isometric view, each square looks like a diamond, with one flat side parallel to the bottom of the screen; there's no perspective, so each square is the same apparent size. I'll assume that's what we're talking about. If it's not, then we're talking 3D math, with matrices or quaternions. A whole 'nother thing. Let me know.
Anyway, if we're doing an old-school isometric view, say the left side of near edge of the board is at x0, y0, and the left edge of the top is at x0+s, y0-h. Then the x coordinate of the left edge of the board at any vertical point y is x0 + s*(y0-y)/h .
Therefore, given any point on the board, you transform x into the equivalent x coordinate in an orthographic view (all sides parallel to the screen edges) by subtracting s*(y0-y)/h. The y coordinate stays the same, of course. Then, given these coordinates, it's a simple matter to compute which square you're in, right?
The old school programmer might precompute a little table of values of s*(y0-y)/h to speed things up.
Actually, I was planning on doing it the other way (like a parallelogram, but rotated a little)
like here, except that program only used keyboard input
another easy, but imperfect way would be to make an Area the size of the image , and then subtracting 4 ellipses from it (one from each corner), which would give a close approzimation. (it would be a little less than the actual size)
but tell me more about the 3D math solution...
Joined: Jan 20, 2005
actually, instead of subtracting ellipses, I could subtract rectangles... I'm thinking I could use a for loop and subtract a bunch of rectangles, each moving with the slope of the line (and do this once for each side)
this may take a little while, so I think I would create one general area, then make copies of it (and translate the copies) to fit where the tiles areTile Image
Joined: Jan 20, 2005
sorry, the link doesn't work, so I will try to illustrate using text: (try to visualize it with 4 rectangles per corner)
You can use either 4x4 matrices or 4-element vectors called "Quaternions" to represent arbitrary rotations and translations in three-dimensional space. If you set up a matrix which transformed the board into the plane of the screen (or the screen onto the board, either way) then that matrix could be used to take the mouse-click coordinates and transform them into coordinates on the plane of the board. This is how you'd do it if you wanted to use any arbitrary transformation for the board, especially a changeable one (the board can move.) It's more math, so it's slower, but it's way more flexible.
There are lots of tutorials on 3d math for game programmers out there -- Google to your heart's content. There are also a number of Java APIs that help you with this: from the simple javax.vecmath package in Java3D to presumably nicer stuff in game engines like jME.
But generally if you have a fixed isometric board layout, then the simple kind of tricks we're talking about here will be better.
Joined: Jan 20, 2005
yes, it is fixed, and thankfully I have managed to get my solution working somewhat, but I think I'll look into that 3D math (not for this project) thanks for your help
Originally posted by karl nilsson: yes, it is fixed, and thankfully I have managed to get my solution working somewhat, but I think I'll look into that 3D math (not for this project) thanks for your help
You really don't need 3D math. Just 2D would work.
The isometric view using implies a certain tansform matrix (or series of equations) to go from the (R)ank and (F)ile measurements of your chess board to the X and Y on the screen. For instance, I could see you using...
Now what you need is the reverse transform to get from an X,Y screen coordinate of a mouse click to rank and file. To get that, you can solve the X and Y equations for R and F. Finding the inverse of the transform matrix solves the same problem.
Let's try one. The home square for White's king pawn covers a range of Rank values of [1,2]. (The integer values for Rank and File give the corners of each square.) The File values are [4,5].
The four corners for that square will be drawn on the screen at... (1,4) --> (201,55) (1,5) --> (218,65) (2,5) --> (201,75) (2,4) --> (184,65)
Notice those four points make a squashed diamond shape on the screen.
Let's say the user clicks right in the middle of that space. Using the inverse equations/transform matrix (X,Y)=(201,65) converts to (R,F)=(1.5,4.5). Sure enough that's right in the middle of Whites king's pawn's home square.
As another example, let's say the user clicks at (X,Y)=(217,56), which is outside the diamond shape but just barely within its bounding box. That screen coordinate converts to (R,F)=(0.58, 4.52). This is in the white king's home square.