Results 1 to 8 of 8

Thread: Picking Tile in staggered isometric map

  1. #1
    Junior Member
    Join Date
    Feb 2009
    Location
    Nevada
    Posts
    11

    Default Picking Tile in staggered isometric map

    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...


    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

  2. #2
    Junior Member
    Join Date
    Mar 2005
    Location
    Vancouver, BC
    Posts
    28

    Default

    There are probably a few ways to go about it. Is this all just in a 2D representation? It would help to know what sort of coordinates you are using to draw the tiles, and how that relates to the coordinates used for selection.

    Also, are you sure the way you have defined rows/columns is the best way to go? If you think in terms of rows and columns sharing edges, rather than points, it might be easier. That is, think of it as rows and columns in a regular grid, then rotate 45 degrees to display, rather than keeping the rows and columns interleaved.

  3. #3
    Junior Member
    Join Date
    Feb 2009
    Location
    Nevada
    Posts
    11

    Default

    Thanks for the input,
    I am drawing the map by iterating through an array that contains map data, each member of the array can contain a number which correlates to a tile. Each number represents a different tile.
    Each other row is offset by 32 to achieve the staggering. Its a pretty standard format for drawing isometric tile maps, from what I read anyways.

    Here is the code used to draw the map...
    Code:
    for (var i = 0; i < rows; ++i) {
    	for (var j = 0; j < cols; ++j) {
    		tTile._y = mapOffSetY + (i*16);
    		// handle odd and even rows differently
    		if (i % 2) {
    		  // Even Row
    		  tTile._x = (mapOffSetX + (j*64))+32;
    		} else {
    		  // odd row
    		  tTile._x = mapOffSetX + (j*64);
    		};
    	}
    }
    I have formulas for retrieving the row and col of the tile that is clicked on by the mouse in a DIAMOND shape isometric tile map but I can't seem to convert this formula in this STAGGERED isometric map style.

    Thanks for any help.

  4. #4

    Default

    I would approach it like this: First find out, in which diagonal (direction down/right) the queried coordinate lies. I would index those diagonals as follows (regarding the start field):

    ...
    (R4,C0): -2
    (R2,C0): -1
    (R0,C0): 0
    (R0,C1): 1
    (R0,C2): 2
    ...

    To calculate that diagonal index (lets call it s), you could, e.g., project the queried coordinate onto the ray which starts at the left corner of (R0,C0) and which has the direction of the upper left edge of (R0,C0). Let this projection be p.

    The next thing you should do is to calculate how many tiles you would have to cross, to reach your coordinate starting from p. This should be pretty straight forward. Let this number be t. Given s and t it should now be relatively simple to calculate the tile-index. For that you should distinguish between the cases s>=0 and s<0.

    Regards,
    Sebastian

  5. #5

    Default

    A small correction: to calculate s and p, projection is not really right. Instead, You can calculate them by intersecting the ray that starts at the left corner of (R0,C0) with the direction of the upper left edge of (R0,C0) with the ray that starts at the queried coordinate with the direction of the upper right edge of (R0,C0).
    Regards,
    Sebastian

  6. #6
    Senior Member
    Join Date
    Jul 2004
    Location
    Isle of Wight, UK
    Posts
    3,863

    Default

    You need to map the screen space coordinate of where you click into the "map space" that the map is in.

    Subtract the position of the top diamond as it is on screen from your clicking point, that gives you a coordinate relative to the map origin.

    Then you munge the X and Y numbers backwards into a new pair of coordinates that would address the map tiles in 2D - 0-63 in X is character one with a pixel location if you need it, 64-127 is cell two, etc.

    Think about where 0 across actually is in 2D coordinates on screen as you scan down the left edge of your graphics - it goes -2 pixels in X for each one it drops in Y by for example.

    It's harder to explain than to do so I'm not going to try, but it's basically the reverse of the logic you use to put the tiles in the right place when you draw them.
    Regards,
    Paul Johnson

    [Great BIG War Game: iOS | Android] [Great Little War Game: iOS | Android] [Fruit Blitz: iOS | Android] [Yachty Deluxe: iOS | Android]

  7. #7
    Junior Member
    Join Date
    Feb 2009
    Location
    Nevada
    Posts
    11

    Default

    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/showthre...-isometric-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;
        }

  8. #8

    Default

    Hi i will be brief, i am doing an isometric game and picking the tile depends on the screen resolution, where the map is centred, and a few other variables.

    Try this

    Code:
    X		=		(MouseX-(MapXPos*MapScale));
    Y		=		(MouseY-(MapYPos*MapScale));
    X		-=		(MapCenterX*MapScale);
    Y		-=		(MapCenterY*MapScale);
    MapTileX	=		(((Y + X/2))/(TILESIZE*MapScale));
    MapTileY	=		(((Y - X/2))/(TILESIZE*MapScale));

    This is from my code so it should work!
    Game development blog luckyredfish.com

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •