Sign in to follow this  
pyrathian

Detecting tile beneath the cursor

Recommended Posts

Hello friends, I am trying to detect which tile is beneath the cursor. It would be great if somebody could post a type of pseudo-code explaining this ( and is the process different with isometric tiles than square tiles? ) Thanks again for the awesome help thus far :p

Share this post


Link to post
Share on other sites
The really important question, the root of the whole decision tree on how to handle it, starts off with; do you have elevations, or is your map flat?

If it is flat, it's just a matter of projecting the mouse cursor onto the plane, breaking your coordinate space into small segments, and testing where in which small segment your cursor lies. There are many tutorials for this in the "resources" section of this site.

If you have elevations, then we need to know much more. There are a few tutorials for this in the "resources" section of this site.

Share this post


Link to post
Share on other sites
One possible solution would be to give each tile a colour ID. Then you do a render pass with just the colour as the output. Once you have this image you can then check the mouse location against it and you have the ID of the tile beneath the cursor.

Share this post


Link to post
Share on other sites
Darg's method works pretty well but there is one gotcha to keep in mind: if the application is running in a different color depth than you expect, you may not have a clean mapping between color and tile since the actual color used to render the tile may end up being different, though hopefully this won't be the case.

Other methods for picking the right tile also depend on what you are using to render OpenGL, DirectX or a home brewed 2D/3D engine.

Share this post


Link to post
Share on other sites
... Also, you can use "simple" conversion functions if you don't plan on ever having height data. The complexity of the function will then depend on what camera motions you allow (is the camera fixed on the ground in one spot, or on a moving player. I'm assuming the camera won't rotate or pitch either.)

Share this post


Link to post
Share on other sites
You should have a function for converting from pixel to tile coordinates and vise versu, with these you would simply convert the pixel location of your mouse to a tile location. I suggest you look into some of the isometric tutorials on this site(under articles) in order to build a firm understanding of the tile layouts. That said these functions are dependent on the specifics of your setup, are you using a staggered map or a diamond map and are you using an ortho projection?

If you're using a staggered map with tiles of a 2/1 aspect ratio here is code that will work.





#define PIXEL_TILE_WIDTH 64
#define PIXEL_TILE_HEIGHT 32


typedef struct
{
float x, y;
}coord_type;

static int_t g_mouse_map[PIXEL_TILE_WIDTH][PIXEL_TILE_HEIGHT] = {
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,
4,4,4,4,4,4,4,4,4,4,4,4,4,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,
4,4,4,4,4,4,4,4,4,4,4,4,4,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,
4,4,4,4,4,4,4,4,4,4,4,4,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,
4,4,4,4,4,4,4,4,4,4,4,4,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,
4,4,4,4,4,4,4,4,4,4,4,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,
4,4,4,4,4,4,4,4,4,4,4,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,
4,4,4,4,4,4,4,4,4,4,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,
4,4,4,4,4,4,4,4,4,4,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,
4,4,4,4,4,4,4,4,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,
4,4,4,4,4,4,4,4,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,
4,4,4,4,4,4,4,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,
4,4,4,4,4,4,4,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,
4,4,4,4,4,4,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,
4,4,4,4,4,4,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,
4,4,4,4,4,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,
4,4,4,4,4,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,
4,4,4,4,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,
4,4,4,4,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,
4,4,4,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,
4,4,4,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,
4,4,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,
4,4,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,
4,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,
4,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,
4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
3,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,
3,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,
3,3,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,
3,3,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,
3,3,3,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,
3,3,3,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,
3,3,3,3,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,
3,3,3,3,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,
3,3,3,3,3,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,
3,3,3,3,3,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,
3,3,3,3,3,3,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,
3,3,3,3,3,3,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,
3,3,3,3,3,3,3,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,
3,3,3,3,3,3,3,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,
3,3,3,3,3,3,3,3,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,
3,3,3,3,3,3,3,3,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,
3,3,3,3,3,3,3,3,3,3,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,
3,3,3,3,3,3,3,3,3,3,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,
3,3,3,3,3,3,3,3,3,3,3,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,
3,3,3,3,3,3,3,3,3,3,3,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,
3,3,3,3,3,3,3,3,3,3,3,3,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,
3,3,3,3,3,3,3,3,3,3,3,3,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,
3,3,3,3,3,3,3,3,3,3,3,3,3,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,
3,3,3,3,3,3,3,3,3,3,3,3,3,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2 };




coord_type convert_point_pixel_to_remainder(coord_type pixel)
{
coord_type remainder;

remainder.x = (int_t)pixel.x % PIXEL_TILE_WIDTH;
remainder.y = (int_t)pixel.y % PIXEL_TILE_HEIGHT;

return remainder;
}




coord_type convert_point_pixel_to_even_tile(coord_type pixel)
{
coord_type tile;

tile.x = (pixel.x / PIXEL_TILE_WIDTH);

tile.y = pixel.y / PIXEL_TILE_HEIGHT;

return tile;
}





int_t convert_point_remainder_to_mouse_map_value(coord_type remainder)
{
int_t mouse_map_value;

mouse_map_value = g_mouse_map[(int_t)remainder.x][(int_t)remainder.y];


return mouse_map_value;
}




coord_type convert_point_pixel_to_tile(coord_type world)
{
coord_type exact_tile;
coord_type even_tile = convert_point_pixel_to_even_tile(world);
coord_type remainder = convert_point_pixel_to_remainder(world);
int_t mouse_map_index = convert_point_remainder_to_mouse_map_value(remainder);


exact_tile.x = (int_t)even_tile.x;
exact_tile.y = ((int_t)even_tile.y * 2);

switch (mouse_map_index)
{
case 1:
break;

case 2:
exact_tile.y += 1;
break;
case 3:
exact_tile.y -= 1;
break;
case 4:
exact_tile.x -= 1;
exact_tile.y -= 1;
break;
case 0:
exact_tile.x -= 1;
exact_tile.y += 1;
break;
}

return exact_tile;
}




coord_type convert_point_tile_to_pixel(coord_type tile)
{
coord_type pixel;

pixel.x = (tile.x * PIXEL_TILE_WIDTH) +
( ((int_t)tile.y&1) * (PIXEL_TILE_HEIGHT) );

pixel.y = tile.y * (PIXEL_TILE_HEIGHT / 2);


return pixel;
}


coord_type get_tile_below_mouse(coord_type mouse_loc)
{
coord_type tile_under_mouse = convert_point_pixel_to_tile(mouse_loc);

return tile_under_mouse;
}






You only need to us convert_point_tile_to_pixel and convert_point_pixel_to_tile(). And if you use ground tiles which are of a dimension other than 64x32 you'd have to rewrite the mouse map array obviously.

Share this post


Link to post
Share on other sites
just divide the mouseposition with tilesize (tile_x = mouse_x/tilewidth) and (tile_y = mouse_x/tileheight) this will give you a value just make sure its within bound tile_x<80 tile_y<40.

Share this post


Link to post
Share on other sites
Quote:
Original post by bASELaRTS
just divide the mouseposition with tilesize (tile_x = mouse_x/tilewidth) and (tile_y = mouse_x/tileheight) this will give you a value just make sure its within bound tile_x<80 tile_y<40.


This will not work.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this