Detecting tile beneath the cursor

Started by
11 comments, last by Zuka 14 years, 8 months ago
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
Advertisement
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.
RIP GameDev.net: launched 2 unusably-broken forum engines in as many years, and now has ceased operating as a forum at all, happy to remain naught but an advertising platform with an attached social media presense, headed by a staff who by their own admission have no idea what their userbase wants or expects.Here's to the good times; shame they exist in the past.
Thanks for the reply, right now it is completly flat, no depth or elevations, etc.!
hehe ;p

[Edited by - pyrathian on July 25, 2009 7:24:00 AM]
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.
Portfolio & Blog:http://scgamedev.tumblr.com/
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.
... 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.)
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     32typedef 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.
Thanks a lot for all the input... I'll be thinking on it quite a bit.

I've got a staggered map using 80x40 pixel tiles... and sorry, but what is an orthogonal projection?
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.
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.

This topic is closed to new replies.

Advertisement