Picking a tile on a STAGGERED isometric map

Community Forums/General Help/Picking a tile on a STAGGERED isometric map

YellBellzDotCom(Posted 2012) [#1]
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


*(Posted 2012) [#2]
Couldnt you use a mask tile and see if a pixel dot is within the mask meaning its selected or a simple if mousex and y are withing the image border then that tile is selected?


Derron(Posted 2012) [#3]
I wont do the work now (lazy mind):

Each diamond (your staggered isometric tiles) is made out of 2 triangles.
For triangles you will find enough algorithms to check whether a coordinate collides with it.

There are also dozens of tons of articles about "polygon hit test" - this is the same. But hey... there must be an easier way to do... and here it is:

using: http://laserbrainstudios.com/2010/08/the-basics-of-isometric-programming/
   local mouseOverTileX:int = floor( (screenOffsetY / tileH) + (screenOffsetX / tileW));
   local mouseOverTileY:int = floor( (screenOffsetY / tileH) - (screenOffsetX / tileW));



bye
Ron


YellBellzDotCom(Posted 2012) [#4]
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.php?376083-Picking-Tile-in-staggered-isometric-map
Maybe try something like this...

    
    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;
    }



Enyaw(Posted 2013) [#5]
Maybe you could look here Click here! as i did post some code sometime ago that could be of some help.


fdfederation(Posted 2014) [#6]
;Map size in number of tiles
Global width_world_size% = 10
Global height_world_size% = 20

;Load tile image
Global tile = LoadImage("GrassIso2.png")
Global terrain_placement_cursor = LoadImage("GrassIso1.png")

;Tile size in pixels
Global width_tile = 128
Global height_tile = 64

;Draws tiled terrain
Function plot_staggered()
	
	Local row%
	Local column%
	Local odd%
	Local x_tile%
	Local y_tile%
	
	For row = 0 To height_world_size
		For column = 0 To width_world_size
			If row Mod 2 > 0
				odd = 1
			Else
				odd = 0
			EndIf
			x_tile = (column * width_tile) + (odd * (width_tile / 2))
			y_tile = (row * height_tile / 2)
			DrawImage(tile,x_tile - width_tile / 2,y_tile - height_tile / 2)
			;Enable text to show tile locations
			Text(x_tile, y_tile, "(" + Str(column) + "," + Str(row) + ")", True, True)
		Next
	Next
	
End Function

; Convert mouse position to tile position
Function terrain_placement(tile)
	
	Local row%
	Local column%
	Local odd%
	Local x_placement%
	Local y_placement%
	Local y%
	Local x%
	
	; indices of odd row numbered tiles
	column = Int(MouseX() / width_tile)
	row = 1 + 2 * Int(MouseY() / height_tile)
	
	; x,y cordinates of center of nearest odd row numbered tile
	x_placement = (column * width_tile) + (width_tile / 2)
	y_placement = (row * height_tile / 2)
	
	x = MouseX() - x_placement
	y = MouseY() - y_placement
	
	; check y position against equations of lines outlining tile boundary
	; recalculate placement position as necessary
	If x<0
		; line of top left border
		If y > (height_tile + x) / 2
			row = row + 1
			x_placement = (column * width_tile)
			y_placement = (row * height_tile / 2)
		; line of bottom left border
		ElseIf y < (-height_tile - x) / 2
			row = row - 1
			x_placement = (column * width_tile)
			y_placement = (row * height_tile / 2)
		EndIf
		
	Else
		; line of top right border
		If y > (height_tile - x) / 2
			column = column + 1
			row = row + 1
			x_placement = (column * width_tile)
			y_placement = (row * height_tile / 2)
		; line of bottom right border
		ElseIf y < (-height_tile + x) / 2
			column = column + 1
			row = row - 1
			x_placement = (column * width_tile)
			y_placement = (row * height_tile / 2)
		EndIf
	EndIf

	DrawImage(tile,x_placement - width_tile / 2,y_placement - height_tile / 2)
	;Enable text to show tile location
	Text(x_placement + 2, y_placement + 2, "(" + Str(column) + "," + Str(row) + ")", True, True)


End Function

;Loop main program
;	"plot" tiles
;Set graphics mode and BackBuffer() for DrawImage()
Graphics(800,600)
SetBuffer(BackBuffer())


;Repeat
	;Until WaitEvent () = $803
While Not KeyHit(1)	
	;Cls
	plot_staggered()
	terrain_placement(terrain_placement_cursor)
	Flip
Wend
;End