How to locate touched tile in an isometric tile map?

Hi, guys,

I’ve an isometric tile map in my game which is created by Tiled.
When player touch the map, I want to know which tile is touched.
In other words, I need to know the location of touched tile in isometric map coordinate system.
But it seems that I can’t get the right location.

First, I get the touch location in screen coordinate by:
CCPoint touchLocation = pTouch~~>locationInView);
touchLocation = CCDirector::sharedDirector~~>convertToGL;
P.S.:
assume that pTouch is a CCTouch pointer.
Then I try to convert the touch location to tile location in isometric coordinate by:
@
CCPoint tilePosFromLocation{
// Tilemap position must be subtracted, in case the tilemap position is scrolling
CCPoint pos = ccpSub);
float halfMapWidth = tileMap~~>getMapSize.width * 0.5f;
float mapHeight = tileMap~~>getMapSize().height;
float tileWidth = tileMap~~>getTileSize.width;
float tileHeight = tileMap~~>getTileSize().height;
CCPoint tilePosDiv = CCPointMake(pos.x / tileWidth, pos.y / tileHeight);
float inverseTileY = mapHeight - tilePosDiv.y;
// Cast to int makes sure that result is in whole numbers
float posX = (int)(inverseTileY + tilePosDiv.x - halfMapWidth);
float posY = (int)(inverseTileY - tilePosDiv.x + halfMapWidth);
// make sure coordinates are within isomap bounds
posX = MAX (0, posX);
posX = MIN (tileMap->getMapSize().width - 1, posX);
posY = MAX (0, posY);
posY = MIN (tileMap->getMapSize().height - 1, posY);
return CCPointMake(posX, posY);
}@

P.S.:
This function is suggested in “Learn iPhone and iPad Cocos2D Game Development”.

It seems that the function tilePosFromLocation doesn’t work well.
If I touched the tile (13, 11), the result from tilePosFromLocation is (12, 16).
I don’t know why.
Do you have any clue or suggestion about this issue?
Thank you!

:frowning:
Is there any one could help?
Thank you!

I don’t understand these codes

float inverseTileY = mapHeight - tilePosDiv.y;
// Cast to int makes sure that result is in whole numbers
float posX = (int)(inverseTileY + tilePosDiv.x - halfMapWidth);
float posY = (int)(inverseTileY - tilePosDiv.x + halfMapWidth);

Why use inverseTileY to compute posX and use tilePosDiv.x to compute posY?

It is a formula.
The mathematics behind it can be found at “www.gandraxa.com/isometric_projection.aspx”.
In fact, you can find the code in Chapter 11 of “Learn iPhone and iPad Cocos2D Game Development” if you have one.

In fact, the formula is not the thing I care.
I just want to locate a touched point in isometric map coordinate.
But I don’t know how to do the projection & coordinate translation, other thing like that in cocos2d-x.
And I have searched a lot online, but couldn’t find anything I can use.

I’m still searching for a solution…
Is there anyone could help?
I’ve been tortured by this problem for several days.
:frowning:

I don’t understand the meaning of the formula, so can not help you.

I see.
Thank you anyway.
:slight_smile:

Finally, I think I know what goes wrong in this issue.
The formula is right, but I misunderstand the “Point” and “Pixel” when calculating.
Thank you, Minggo!

Hey Raymond. Glad you got it working. Any chance you could share some of your code. I ask a very similar question but got no response. I just want an event with the tileid that was touched (even if there isn’t an actually tile there). It seems like it would be common sense but there are two many coordinates systems and I don’t understand the tile map system well enough. I would really appreciate it!

Thanks,

Jim

As I said “The formula is right, but I misunderstand the”Point" and “Pixel” when calculating."
The formula has handled the difference between two coordinate system correctly.
But there is another difference, the touched location is in “point”, but in tile map, offset & width, height are all in “pixel”.
So we need to convert point to pixel before calculating tile position. What I did is add the code below to tilePosFromLocation

pos = ccpMult(pos, CCDirector::sharedDirector()->getContentScaleFactor());

Let me know if it works on your side, thank you.

I don’t know why you don’t just use:

CCSize tileSize = tileMap->getTileSize(); CCSize mapSize = tileMap->getMapSize(); CCPoint pos = ccpSub(location, tileMap->getPosition()); float posX = floor(pos.x / tileSize.width); float posY = mapSize.height - floor(pos.y / tileSize.height);

This works for me.

Hi,
This function is work for orthogonal not for Iso-metric, if some one have any idea about calculate point of iso-metric according touch point of screen.

Thanks
Vinod

Here is what I’ve been using for my own isometric engine. The tiles are setup like this image: http://garrypettet.com/images/forum_images/5%20col%20x%205%20rows.png with the tile (0,0) sitting on world coordinate (0,0) for simpler maths.

vec2f gridToWorld(vec2i gridpos)
{
    return  vec2f( (gridpos.x * XSPACING) - (gridpos.y * XSPACING) ,  -(gridpos.x * YSPACING) - (gridpos.y * YSPACING)  ); 
}

vec2i worldToGrid(vec2f worldpos)
{
    vec2i ret;
    ret.x = (int)( (-worldpos.y + (worldpos.x/2.0) ) / XSPACING + 0.5f);
    ret.y = (int)( (-worldpos.y - (worldpos.x/2.0) ) / XSPACING + 0.5f);
    return ret;
}

Hi, anyone knows how to convert the position from tilemap to screen coordinate? Or any point to the documentation is highly appreciated… I don’t quite understand the isometric part, and so far it has only been guess work… I can’t even place isometric maps with different size reliably on screen coordinate (0.0f, 0.0f) :frowning:

Btw, I’m using:
CCPoint CCTMXLayer::positionAt(const CCPoint& pos)

I’m inputting my screen coord (touch coord) as param pos, and expect it to return the center position of the tile touched in my screen coord as well, but it doesn’t look like it is returning that or even tile coordinate…