Mouse coordinates to tile (not 'another' topic)

Started by
26 comments, last by wicked_wesley 19 years, 11 months ago
Howdy,

I don't really know what you mean wiht this:
if (readpixel(point(tx,ty)) <> trans_color)
mappoint(x,y) = point(x,y);

I guess "If the clicked pixel coordinate equals to some color......" I don't get the rest of it. There are various ways to check where someone has clicked, but the one I'm trying to use is one of the fastest, as far as I know. If you check which coordinate is clicked during the drawing of every tile, like this:
for(...)  {  if(clickedCoordiantes==drawingCoordinate)    clickedMap=bla bla;  drawTile():  }  


It is gonna make your drawing slower, 'caus it needs to check it with every tile you draw. So I don't think it is a good idea to use it, especially when using the some what slower Java.

I still don't have any drawings/pictures to show you my idea, but I'm working on it. Basicly, I make a grid of square tile (64x32) and get the clicked square tile and convert that to an iso tile. (You probally don't know what I mean, hehehe )

Wesley

[edited by - wicked_wesley on November 23, 2003 1:06:54 PM]
Have a nice dayWesley
Advertisement
quote:Original post by wicked_wesley
VertexNormal, I tried what you have posted, but I didn''t work I tried like 10000 million different ways, but none seem to work.


Hmmm... yes, but did you try it the right way?

Maybe some pictures might help.

This is a representation of a tile in world coordinate space and the same tile in screen coordinate space:


As you can see, the tile is subdivided into 4x4 units (the blue blocks represent world coordinate locations). The tile size in this case would be 16x8 (there are rows of padding added to a tile in the real world, to make the tile fit the dimensions.)

Now, each world coordinate location is represented by a 2x1 block of pixels in the tile map (conforming to the 2:1 ratio imposed by tiles that are exactly twice as wide as they are tall). Note that as you advance by 1 in the X direction in world coordinate space (the top picture), the screen coordinates (bottom picture) change by 2 in the X direction and 1 in the Y direction, to advance to the beginning of the next blue block in the X coordinate axis. I derived the earlier formulae by looking at a diagram like this and figuring out how the coordinates change when you move along any of the axes. I built a table of the various offsets, then figured out the formula to perform the mapping.

Take a look at the location with the dot. In world coordinate space, this location is (2,1). In screen space, this location is (8,3), relative to the origin. (Actually, it is the block (8,3)-(9,3) ).

The origin of the tile is at (0,0) in world coords, and at (6,0) in screen coords (corresponding to the top corner of the tile). So to prove that the formulae listed earlier work, we need the corresponding deltas to the location with the dot from the origin:
DeltaWorldX=2DeltaWorldY=1DeltaScreenX=8-6   // Distance from dotted location to origin            =2DeltaScreenY=3 

We can plug these into the equations to show that they equal.
DeltaScreenX=2*DeltaWorldX - 2*DeltaWorldY            =2*2 - 2*1            =2DeltaScreenY=DeltaWorldX + DeltaWorldY            =2+1            =3DeltaWorldX=(DeltaScreenX + 2*DeltaScreenY) / 4           =(2 + 2*3)/4           =2DeltaWorldY=(2*DeltaScreenY - DeltaScreenX) / 4           =(2*3 - 2) / 4           =1 


So, basically, this algorithm creates a mapping of distances in screen space to distances in world coordinate space. If you know the distance in pixels between two points on the screen, you can calculate the distance in world coordinates between the world locations corresponding to those two points. As long as you know that the center of the screen corresponds to the point at which the map is centered at, then you can easily find the distance in screen coordinates between the center of the screen and the cursor location, then plug that distance into the formula to find the distance from the map center to the point in the map corresponding to the cursor location.

I really don''t know how else to explain it without a lot more visual aids or somesuch. It does work, though.

Anyway, good luck, and let us know how your idea turns out.


Josh
vertexnormal AT linuxmail DOT org

Check out Golem: Lands of Shadow, an isometrically rendered hack-and-slash inspired equally by Nethack and Diablo.
Easiest is to realize that 3D geometry concepts can be applied to 2D geometry as well.

Assuming you have the "top left" corner of tile (0,0) at position x0,y0, and that your tiles grow X-up-right by xx,yx and Y-down-right by yx,yy, you can use simple dot products to figure out the clicked tile:

int mx = mouse.X - x0;
int my = mouse.Y - y0;
tileX = floor( mx / xx + my / xy );
tileY = floor( mx / yx + my / yy );

Note that, in your case, the value of yy is likely negative, assuming positive is "up" and "right".

enum Bool { True, False, FileNotFound };
Hey you! Yes you, behind that screen!

Wow, VertexNormal, are you a human? Becaus humans don''t help each other that much! I really like you! All the time you have spend to those posts, just to help others with there problems. I wish there were more people like you. Vertex rules! (hey nice idea: let''s all put this in our signature: "Vertex for president!" )

I finally figured my whole idea out, and it works pixel precise(sp?) I will post the code later today, caus it looks kinda messy right now, hehee Just wanted to let you know that I have found a way (all by my self ) to calculate the tile clicked on. So everyone out there, don''t worry anymore! your hero is here!

Thank you all!
Yours truly,
Wesley
Have a nice dayWesley
quote:Original post by wicked_wesley
Hey you! Yes you, behind that screen!

Wow, VertexNormal, are you a human? Becaus humans don''t help each other that much! I really like you! All the time you have spend to those posts, just to help others with there problems. I wish there were more people like you. Vertex rules! (hey nice idea: let''s all put this in our signature: "Vertex for president!" )

I finally figured my whole idea out, and it works pixel precise(sp?) I will post the code later today, caus it looks kinda messy right now, hehee Just wanted to let you know that I have found a way (all by my self ) to calculate the tile clicked on. So everyone out there, don''t worry anymore! your hero is here!

Thank you all!
Yours truly,
Wesley



Well, thank you. I''m glad to be of help. I actually tend to look on topics that I am truly interested in such as this as an excellent opportunity to try to develop my writing skills, and to work on my ability to explain things as clearly as I can. I also love games in the isometric format, and if by trying my best to help people learn, stay motivated, and complete their projects can help the isometric "genre" to thrive and grow among the hobbyist community, then I am more than glad to spend a little time. I might not always be right, but I am willing to try to help when I can.

Of course, I don''t know how the whole "Vertex for President" would work out; things like that tend to go straight to my head. You have no idea of the absolute monster I could turn into.

Anyway, I''m looking forward to seeing what you figured out. Good luck.


Josh
vertexnormal AT linuxmail DOT org

Check out Golem: Lands of Shadow, an isometrically rendered hack-and-slash inspired equally by Nethack and Diablo.
quote:Original post by VertexNormal
Well, thank you. I'm glad to be of help. I actually tend to look on topics that I am truly interested in such as this as an excellent opportunity to try to develop my writing skills, and to work on my ability to explain things as clearly as I can. I also love games in the isometric format, and if by trying my best to help people learn, stay motivated, and complete their projects can help the isometric "genre" to thrive and grow among the hobbyist community, then I am more than glad to spend a little time. I might not always be right, but I am willing to try to help when I can.

Of course, I don't know how the whole "Vertex for President" would work out; things like that tend to go straight to my head. You have no idea of the absolute monster I could turn into.

Anyway, I'm looking forward to seeing what you figured out. Good luck.


Hey,

Well, most presidents look nice, and turn into monsters once they have the power I'm glad to see that you are trying to keep the isometric community 'standing'. I'm now busy with a tutorial about the isometric basics, and I will make more tutorials when I counter more problems or hard developing parts, I will also make them as much 'language independent' as I can and I might add some C/C++ (and ofcourse Java) code listnings, as example.

About my idea

I hope that noone has posted this, then I would look like a fool. Because my english isn't that good, I didn't understand all the tutorials, so if I stole your idea, don't blame me!

I have figured out a simple way to get the tile where someone has clicked on, using a mousemap.

The Theory

I make a square grid around the isometric tiles. (not really, just in my head) Like this:



**A square is not an isometric tile, but a square tile (which is also 64x32)**

Ofcourse, it's easy to get the square where someone has clicked. So after you get the square where was clicked, you only need to translate it into the according isometric tile. After a couple of hours sitting, staring, eating and bang-head-to-table I have found the formula to translate a square into a tile. So this is what I do:

+Translate the Mouse coordinates to the Square coordinates
+Translate the Square Coordinate to the Isometric Tile.

Simple example (this is probaly not correct, jsut to show how it works)

You clicked on the screen coordinate: 125,435.
You translate it to the Square coordiante: 6,9.
Now you translate it to the Isometric tile: 3,4.

Et voila , you got the isometric tile.

I hope this still sounds understandable, if not I will try to make some images to explain it better.

The code

Now off to the important thing; the actual formulas.

How to translate a clicked coordiante to an square? That isn't to hard, that's just like getting a tile with an top-down view.

*note* I base my whole map that gets drawn on the center tile, so you can easly change which piece of the map gets drawn.

This isn't actual code, I removed things like variable declaretions and the ";" (that would only make it harder to read)

sqX=mouseX+topCoordinateX
sqY=mouseY+topCoordinateY

**The numbers (64 and 32) are the width and the height of one tile (Square and Isometric)**
sqX=sqX/64
sqY=sqY/32

tileX=sqX-centerTileX+sqY
tileY=sqY+centerTileY-sqX

Variable Explaination

sq(X/Y) the square where someone has clicked on (Not the Isometric Tile)

tile(X/Y) this is what we want to know, the Isometric Tile where someone has clicked on

topCoordinate(X/Y) this is the left upper pixel coordinate, from where you start drawing. Also called the 'offset' I believe (not sure, so I wouldn't name it like that)

centerTile(X/Y) the center tile of the map you drawed , not the center of the whole map(this tile could basicly be every tile)

After you got the tile, you need to use the mousemap to change the tile.

I hope this has explained some stuff. If you want, I can post the Java source.

I hope this is understandable, as you can see, I'm also trying to develop my (English) writing skills

Have a good day!
Wesley

[edited by - wicked_Wesley on November 28, 2003 2:06:05 PM]

[edited by - wicked_Wesley on November 29, 2003 2:24:28 PM]
Have a nice dayWesley
See my post in this topic:

Link
[ PGD - The Home of Pascal Game Development! ] [ Help GameDev.net fight cancer ]
Hi

I have read your post, and the way you calculate which tile is clicked on. Only, your code is (almost) like chinese for me. Actually I understand it, except the Trunc() method. I never heard of it, and I got no idea what it does.

If you have read all the posts, you can see I have found a solution to my problem

Wesley
Have a nice dayWesley
quote:Original post by wicked_wesley
I have read your post, and the way you calculate which tile is clicked on. Only, your code is (almost) like chinese for me. Actually I understand it, except the Trunc() method. I never heard of it, and I got no idea what it does.
Actually that code was in Delphi. The Trunc() function converts a floating point variable to an integer, using truncation as opposed to rounding.

If you want that in C:

OffsetX and OffsetY are ints describing the position of the origin of the map relative to the origin of the screen.
ScreenX and ScreenY are ints describing the point on the screen (in this case the position of the mouse)
MapX and MapY are floats describing the position on the map.
temp1 and temp2 are intermediate values, which don't represent any physical quantity.
/* Map to Screen  */ScreenX = (int)(32 *(MapY + MapX))- OffsetX;ScreenY = (int)(16 *(MapY - MapX))- OffsetY;/* Screen to Map */int temp1 = (ScreenX + OffsetX);int temp2 = 2 *(ScreenY + OffsetY);MapX = (temp1 - temp2)/ 64;MapY = (temp1 + temp2)/ 64;  

I derived the Screen-to-Map formulae mathematically from the Map-to-Screen formulae.

I would have thought this method was better, since it does not involve using a mousemap.

[edited by - Useless Hacker on November 29, 2003 2:48:08 PM]
[ PGD - The Home of Pascal Game Development! ] [ Help GameDev.net fight cancer ]
Wesley, Useless Hacker is right: for your style of isometric engine you don''t need anything as complicated and fiddly as mousemaps. You can simply convert between screen and tile co-ordinates using two simple formulae, already provided by Useless Hacker above - although you''d have to modify them a bit to suit your exact system. Which I''ll do for you now actually:

Given the size of your tiles (64x32) and the way you order them (you have the origin as the left-most point), to get the tile co-ordinates from the screen co-ordinates you use (in C):

tx = ((sx - mapx) / 64) - ((sy - mapy) / 32);
ty = ((sx - mapx) / 64) + ((sy - mapy) / 32);

where:
(tx,ty) are the tile co-ordinates
(sx,sy) are the co-ordinates of the mouse on the screen
(mapx, mapy) are the co-ordinates of the map''s origin relative to the upper-left corner of the screen.

To understand what (mapx, mapy) represent, look at the image you gave just above (which I''ll try to insert here, but I don''t really know how to use this forum, so it may not appear):



If you assume the white rectangle is the screen, then the origin of the green tilemap (which is halfway down the left side of the rectangle) would be at (0, 80). Therefore mapx = 0 and mapy = 80.

[And if the player walked down the screen, the tilemap would scroll upwards, mapy would decrease. If the player walked to the right, the tilemap would scroll to the left, and mapx would decrease. And so on.]

So if the mouse was clicked at some random point, say (100, 40) you would calculate the tile co-ordinates thusly:

tx = ((sx - mapx) / 64) - ((sy - mapy) / 32);
ty = ((sx - mapx) / 64) + ((sy - mapy) / 32);

so:
tx = ((100 - 0) / 64) - ((40 - 80) / 32);
ty = ((100 - 0) / 64) + ((40 - 80) / 32);

tx = 1.5625 - (-1.25) = 2.8125;
ty = 1.5625 + (-1.25) = 0.3125;

The tile co-ordinates are precise; truncate them to get the index of the tile: (2,0) in this example. If you look at the map and roughly trace along 100 pixels, and down 40 pixels, you will see you end up on tile (2,0).

The maths involved here is incredibly simple: plonk your finger on the left-most point of some tile on the screen then move it (your finger) to the right 64 pixels (until you''re at the tile''s right-most point). You increased the screen''s X co-ordinate by 64, and the tile''s X and Y co-ordinates increased by one each. So now you know how the screen''s X co-ordinate affects the tile co-ordinates. Now do the same action from the tile''s top point to its bottom point. You increased the screen''s Y co-ordinate by 32 pixels, and increased the tile''s Y co-ordinate by one and decreased the tile''s X co-ordinate by one. Combine these and you end up with the formulae above.

The other way to think of it, of course, is to say that at some point you''ll know that the player is standing at some given tile co-ordinates [eg. (3.4, 2.25)] and you want to draw the image at the corresponding screen location. So you must have some way of converting from tile co-ordinates to screen co-ordinates - simply reverse the process (which gives the formulae above).

Sorry to waffle on like this; the process of converting between tile and screen co-ordinates for a simple (no elevations, etc.) isometric tilemap is so easy to do but so long-winded to explain in general.

The above DOES work for your type of tiles (assuming my assumptions above were correct) - if I''ve been unclear about anything in this too-long post, just ask.

-hotstone

This topic is closed to new replies.

Advertisement