GPWiki.org
GPWiki.org
It is currently Thu May 23, 2013 3:23 pm

All times are UTC




Post new topic Reply to topic  [ 9 posts ] 
Author Message
PostPosted: Mon Dec 17, 2012 3:40 am 
Prolific Poster

Joined: Sat Mar 07, 2009 5:32 am
Posts: 19
Location: Nevada
Hello!
I have been looking and trying for quite a while now, but can't seem to work out an algorithm for figuring out which tile is selected on a staggered isometric map using 64x32 tiles with a diamond shape inside.

Here is a pic of my map...
Image

The first row is drawn, then the x is offset to the right by 32 and the next row is drawn.

Anyone have any good math skills to throw some algorithms my way for this?
Thanks for any help!

PS: My math isn't exactly top notch, so please keep that in mind. Smiley

_________________
Life is just a game, learn to play!
------------------------------------------
╬-YellzBellz! Online Games, Programming and More!-╬ :D


Top
 Profile  
 
PostPosted: Mon Dec 17, 2012 3:49 am 
Grand Optimizer
User avatar

Joined: Mon Jan 17, 2005 6:01 pm
Posts: 352
Location: Canada
There's probably some wierd solution involving trigonometry or some other advanced geometry, but the more I look at your picture, the more i get an idea.. What if you were to calculate the exact center of each tile, and simply do a check on MouseClick as to which "center" is closest to the mouse cursor?

Not 100% sure if this methodology would work, but the more I study the shapes in your picture the more I feel it would work. Who knows, but it's probably worth a shot.

EDIT: On second thought. The elongated nature of the tiles horizontally might result in some incorrect results near the edge of the tile.. but if the tiles were squished in a bit, it would likely work fine.

_________________
"None are more hopelessly enslaved than those who falsely believe they are free."
"It is no measure of health to be well adjusted to a profoundly sick society."
"Hope is the first step on the road to dissapointment." -Jonah Orion
http://tankzgame.blogspot.com


Top
 Profile  
 
PostPosted: Mon Dec 17, 2012 3:59 am 
Prolific Poster

Joined: Sat Mar 07, 2009 5:32 am
Posts: 19
Location: Nevada
When I was sitting there trying to crunch out a method of my own, I thought of that too. I printed out tons of pics of a tile and tried to calculate what it would take to figure it out, but my brain turned to mush.

There is a very simple math formula for figuring this on a standard diamond shape isometric map which works great, but I changed the map style to the staggered type which of course throws everything off.

I know someone out there has this little golden tidbit! :D

Thanks for the input though!

_________________
Life is just a game, learn to play!
------------------------------------------
╬-YellzBellz! Online Games, Programming and More!-╬ :D


Top
 Profile  
 
PostPosted: Mon Dec 17, 2012 4:52 am 
Grand Optimizer
User avatar

Joined: Mon Jan 17, 2005 6:01 pm
Posts: 352
Location: Canada
I think I may have thought of something.

Another way to look at it is you need to determine which "Column" and which "row" of tiles your mouse cursor is in. But how do you do that with squashed tiles? You need to "draw" a diagonal line from the mouse cursor (exactly parallel to your grid) up and to the right, until the Y value is 0. Envision this - The pic you uploaded - the very top left of the image (the white corner) .. that would be 0,0.

You said your tiles are 64 x 32. thats twice as wide as they are high. We can use that to get the same angle as we draw our own line. up one, right two. make a variable that holds a copy of X,Y of the mouse.. increment the Y by -1, and the X by 2 That should generate a line of the same angle as your grid. Stop the operation when the y is 0.(at the top). Once the Y is 0, you can look at the X value and determine in between which 2 grid vertices it sits, and that will tell you which 'column' your in. Use the same logic going up LEFT until X is 0 and use the Y to determine which "row" you're in.

Do you sorta see what I mean? Not sure if I'm explaining it very well. Also not 100% sure if it would work, but it seems feasible.

_________________
"None are more hopelessly enslaved than those who falsely believe they are free."
"It is no measure of health to be well adjusted to a profoundly sick society."
"Hope is the first step on the road to dissapointment." -Jonah Orion
http://tankzgame.blogspot.com


Top
 Profile  
 
PostPosted: Mon Dec 17, 2012 12:54 pm 
Technomaniac

Joined: Sun Dec 05, 2004 11:27 am
Posts: 3249
Location: Sydney, Australia
One of the sneaky but simple ways of doing it is to create a bitmap that looks like this:

Code:
000012222
001111122
111111111
331111144
333314444

Where 0, 1, 2, 3, and 4 are different colours, and you make it so that the "1" section is the same size as one of your tiles.

You can then imagine that there is a grid of these bitmaps over the top of your map. When you want to work out which tile someone is clicking on, you work out which one of these bitmaps it is, then check the colour of the pixel they clicked on. Apply some simple maths, and you should be good.

(note that the "bitmap" can just be lookup table/array in your code)

_________________
Trying is the first step towards failure
b


Top
 Profile  
 
PostPosted: Mon Dec 17, 2012 7:42 pm 
Bytewise

Joined: Sun Oct 16, 2011 3:09 pm
Posts: 277
Location: Here (where else?)
And this is the easy case, all nice and flat :p

The problem becomes quite simple if you draw a rectangle around R0,C0 and around R0,C1 and around R0,C2, and ...
and around R2,C0, and R2,C1 and ...
and ...

This gives you a nice rectangular grid, where position (x,y) of Rx,Cy is easy to compute. The horizontal/vertical distance from the left/top line of the rectangle is also easy to derive then.
Still with me?

Next, split your rectangle in 4 sub-rectangles, by one horizontal line across from left to right, and one one vertical line down through the middle. Which sub-rectangle you are in is then also easy to decide from the distance from above.

For the top-left and bottom-right sub-rectangle, the dividing line runs from the left bottom to right top corner. For the purpose of the discussing, assume top-left has coordinate (0, 0), left-bottom (0, 1), and right-top (2, 0)

Warning: Math ahead!
Code:
General form of a line:  y = a*x + b
(0, 1) at the line -> 1 = a*0 + b  -> b =1
(2, 0) at the line -> 0 = a*2 + 1 -> a=-1/2
thus the line through (0, 1) and (2, 0) has the formula y = -1/2*x + 1
written somewhat differently y + 1/2*x - 1 = 0
Now comes the smart part. This line formula can also be seen as a distance function of all points to the line. Points on the line have a distance 0 of course, eg (1, 1/2) -> 1/2 + 1/2 * 1 - 1 -> 0
Points away from the line get other values, eg (0,0) -> 0 + 1/2*0 - 1 -> -1
and (2,1) -> 1 + 1/2 * 2 - 1 -> + 1

In other words, for a point in the left-top or bottom-right sub-rectangles, you can with some simple arithmetic decide whether it is in the left-upper half ( < 0 ), on the line itself ( == 0 ), or in the right-bottom half ( > 0 ).
Obviously, you can do the same kind of trick in the other two sub-rectangles.

_________________
My project: Messing about in FreeRCT, dev blog, and IRC #freerct at oftc.net


Top
 Profile  
 
PostPosted: Wed Dec 19, 2012 4:57 am 
Prolific Poster

Joined: Sat Mar 07, 2009 5:32 am
Posts: 19
Location: Nevada
I appreciate the help. It being the work week, I didn't get a chance to really put some time into any solution and I definitely am not going to post the embarassing hack I was attempting.

I did get a plug and play solution involving some math equations that are quite a bit beyond me that I will post for anyone running into the same situation. It works great!


dawsonk
http://www.kirupa.com/forum/showthread. ... metric-map
Maybe try something like this...

Code:
   
    var tileW = 64;
    var tileH = 32;
    var rows = 8;
    var cols = 4;

    for (var i = 0; i < rows; ++i) {
            for (var j = 0; j < cols; ++j) {
                    tTile = _root.attachMovie("Tile", "R" + i + "C" + j, _root.getNextHighestDepth());
                    tTile._x = (tileW * j) + ((i % 2 == 1) ? 32 : 0);
                    tTile._y = (tileH / 2) * i;
            }
    }
    onMouseDown = function () {
            var ax, ay, bx, by;
            var cx = _xmouse;
            var cy = _ymouse;
            var posX = (_xmouse / 32) >> 0;
            var posY = (_ymouse / 16) >> 0;
            if ((posX % 2) == (posY % 2)) {
                    ax = (posX) * 32;
                    ay = (posY + 1) * 16;
                    bx = (posX + 1) * 32;
                    by = (posY) * 16;
                    if (getPos(ax, ay, bx, by, cx, cy) < 0) {
                            trace(((posY / 1 >> 0) - 1) + " : " + ((posX / 2 >>0) + ((((posY / 1 >> 0) - 1) % 2 == 0) ? 0 : -1)));
                    } else {
                            trace((posY / 1 >> 0) + " : " + (posX / 2 >> 0));
                    }
            } else {
                    ax = (posX) * 32;
                    ay = (posY) * 16;
                    bx = (posX + 1) * 32;
                    by = (posY + 1) * 16;
                    if (getPos(ax, ay, bx, by, cx, cy) < 0) {
                            trace(((posY / 1 >> 0) - 1) + " : " + (posX / 2 >>0));
                    } else {
                            trace((posY / 1 >> 0) + " : " + ((posX / 2 >> 0) +((((posY / 1 >> 0) - 1) % 2 == 0) ? -1 : 0)));
                    }
            }
    };
    function getPos($ax, $ay, $bx, $by, $cx, $cy) {
            // below = 1, above = -1, on = 0;
            var slope = ($by - $ay) / ($bx - $ax);
            var yIntercept = $ay - $ax * slope;
            var cSolution = (slope * $cx) + yIntercept;
            if (slope != 0) {
                    if ($cy > cSolution) {
                            return $bx > $ax ? 1 : -1;
                    }
                    if ($cy < cSolution) {
                            return $bx > $ax ? -1 : 1;
                    }
                    return 0;
            }
            return 0;
    }

_________________
Life is just a game, learn to play!
------------------------------------------
╬-YellzBellz! Online Games, Programming and More!-╬ :D


Top
 Profile  
 
PostPosted: Wed Dec 19, 2012 9:45 am 
isn't this implementation of solution that Alberth suggested?


Top
  
 
PostPosted: Thu Dec 20, 2012 5:18 am 
Bytewise

Joined: Sun Oct 16, 2011 3:09 pm
Posts: 277
Location: Here (where else?)
Looks like it.

I found an optimization; if you mirror the x-coordinate relative to the center in the top-right and bottom-left sub-rectangles (ie, do x = 2-x first), you'll end up with the same situation as in the top-left and bottom-right sub-rectangles, and you can treat all sub-rectangles in the same way w.r.t. deciding in which part of the sub-rectangle you are.

_________________
My project: Messing about in FreeRCT, dev blog, and IRC #freerct at oftc.net


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 9 posts ] 

All times are UTC


Who is online

Users browsing this forum: No registered users and 3 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group