Here we go with another newbie question
I'm rendering my map with 2 nested for loops.
It looks like this:
.. .. 01 .. ..
.. 02 06 ..
.. 03 07 11 ..
04 08 12 16
05 09 13 17 21
10 14 18 22
.. 15 19 23 ..
.. 20 24 ..
.. .. 25 .. ..
Now, I've been working in an algorithm that can detect the tile where the cursor is, but failed miserably.
I think the problem is I'm storing the tiles in a way that doesn't help at all.
Currently this is what I have:
How would you guys do this?
I based my design on something I read on one gamedev site that I'm not sure still has the article.
But basically, I had a couple lookup tables. something like the following:
It's something like that anyhow. iso_tile_x and iso_tile_y is the coords of the selected tile.
I'd have pulled out my old iso engine code, but Its all stuck on a backup CD somewhere.
Hope that helps.
Another way would be to use transformations.
Edit: I could elaborate further on that if you showed me your tile.
Edit: On wikipedia there is an article on how to do that without transformations: http://en.wikipedia.org/wiki/Video_games_with_isometric_graphics#Mapping_screen_to_world_coordinates
@Thomas
In your example are you filling the array pixel by pixel?
@Aike
So far I've been working with 32x32 tiles.
Based on what is explained in your link I made this
// tiles are 32x32 // map is 30x30 int virtualTileX = x / 32; int virtualTileY = y / 32; int numberOfTilesInX = 30; int isoTileX = virtualTileX - (numberOfTilesInX / 2); int isoTileY = virtualTileX - (numberOfTilesInX / 2);
It doesn't work 100% but the pattern is there.
It just takes as 0,0 the tile #2 in the picture, instead the one in the top corner.
(My map is 30x30, this one is just an example)
{"name":"11392040083_c62b99616a_o.jpg","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/8\/6\/86cd6d81989d9344399b4313512f240b.jpg","w":700,"h":369,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/8\/6\/86cd6d81989d9344399b4313512f240b"}
I guess I just need to figure how to make that correction and it will be working.
EDIT: mmm now I check better the 0 in the X axis is not exactly in the middle of the row, but int the tile #13.
@Thomas
In your example are you filling the array pixel by pixel?
Yes. tile_map_table is a map of each pixel in a tile to the offset needed to adjust the tile index location.
just doing a division and modulo of the mouse position only works for square tiles. You need to adjust those positions based on where the point is on the diamond shape.
If you use 32x32 tiles, they must be just 45 degrees rotated squares, right? In this case you just need to apply rotational transformation.
ALLEGRO_TRANSFORM transform; al_identity_transform(&transform); al_rotate_transform(&transform,ALLEGRO_PI/4); //later float isox=mousex; float isoy=mousey; al_transform_coordinates(&trans,&isox,&isoy);
But that would be pure coordinates, if you need tile coordinates, you would need to divide that by your tile size in isometry, which in your case should be about 22.6272:
int tilex = isox/22.6272; int tiley = isoy/22.6272;
This should probably work. There might be some inconsistencies since your world coordinate grid and screen coordinate grid do not start at the same point.
Can you please explain how to do it in A4?
I'm not sure, but I believe you do it like this:
Or you could just use Thomas's method. You do this by just dividing your map into squares by dividing mouse coordinates by tile size (32), in this square one isometric tile is in the center and four others are in the corners. You need to figure out which one is in the center, this will depend on where your coordinate grid starts. And then compare the (mousex/32; mousey/32) with the tile map table. This approach should be less computation intensitive, I think I heared that it mattered in the past but shouldn't matter now.
This can be done much easier..
when the mouse ison the map, hide the mouse and enable a special tile selector.
place the tile selector on the tile closest to the mouse.
then move the tile selector according to the delta mouse movement
place the tile selector on the tile closest to the mouse.
Am I missing something or I would be facing exactly the same problem than now?
http://stackoverflow.com/questions/6915555/how-to-transform-mouse-location-in-isometric-tiling-map
A way to transform coordinates to tile is given here in the accepted answer. I think it may be helpful.
I don't know what is the problem but nothing seems to work for me.
Tried what your guys suggested plus everything in the first 6 or 7 google pages, I disabled everything cameras related to keep it simpler, but still can't get it working.
I will try to extract the relevant part of the code and post it here.
I use the following function wich works if you give it the right mousemap for your tiles.
Here is some code for drawing the needed mousemap:
Please note that you only need to preload mousemap bitmap one time.
In the code when I need to know which tile I'm on, I'm just doing this (considering it also has scrolling):
I coded this from some gamedev articles:
http://archive.gamedev.net/archive/reference/list56f4.html?categoryid=198
particularly:
http://archive.gamedev.net/archive/reference/articles/article747.html
http://archive.gamedev.net/archive/reference/articles/article748.html
Thank you GullRaDriel, I will try it next, but I would like to show you guys what I have right now.
{"name":"B0TVn.png","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/c\/b\/cbec5f1fbb7b29c55bcb7d0cf1363225.png","w":390,"h":202,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/c\/b\/cbec5f1fbb7b29c55bcb7d0cf1363225"}
I rendered the tiles like above.
the sollution is VERY simple!
first thing:
my Tile width and height are both = 32 this means that in isometric view, the width = 32 and height = 16! Mapheight in this case is 5 (max. Y value)
y_iso & x_iso == 0 when y_mouse=MapHeight/tilewidth/2 and x_mouse = 0
when x_mouse +=1, y_iso -=1
so first of all I calculate the "per-pixel transformation"
TileY = ((y_mouse*2)-((MapHeight*tilewidth)/2)+x_mouse)/2;
TileX = x_mouse-TileY;
to find the tile coordinates I just devide both by tilewidth
TileY = TileY/32; TileX = TileX/32;
DONE!! never had any problems!
My code
My tiles are 32x32 same as in the example, but they don't change the width/height relation.
This is how I'm rendering them (30x30 map)
for(int i = 0;i < this->total_tiles;i++) { for(int j = 0;j < this->total_tiles;j++) { this->tile_x = (j * (this->tile_w / 2)) + (i * (this->tile_w / 2)); this->tile_y = (i * (this->tile_h / 2)) - (j * (this->tile_h / 2)); } draw_sprite(this->buffer, this->tile1, this->tile_x, this->tile_y); }
And this is what I get
{"name":"11411734803_b0a23afc7a_o.jpg","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/5\/4\/54b523d1eae42e58b4f65f4651730062.jpg","w":973,"h":610,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/5\/4\/54b523d1eae42e58b4f65f4651730062"}
Screen to map conversion isn't working.
At 0,0 gives me 7,-7.
This should not be that hard.
This can be solved with simple linear equations, transformations, and inequalities. First decide where on your map the isometric coordinate (0.0,0.0) is. For arbitrariness's sake make the positive x-axis going up and to the right, and the positive y axis going up and to the left in isometric space.
These coordinates will be known as isomap_world_x, and isomap_world_y in world space. We need to first change from screen space to world space, and then from world space to iso space.
A brief explanation of the method used - first find the equation of the line of the iso x-axis in real space. (y = (H/W)*x). Replace y by the expression (y - N*H) where N is the x coord in iso space and then solve for N. Repeat for the equation of the line of the iso y-axis in real space. Once you have both solved, combine them and then solve for the xy coords from the iso coords.
The tricky part is converting back from iso to screen space, but easy enough if you figure out the equations for iso space from screen space.
mousex = (ISO_TILE_WIDTH/2.0f)*(isox - isoy); mousey = (ISO_TILE_HEIGHT/2.0f)*(isox + isoy)); mousey *= -1; mousex += isomap_world_x; mousey += isomap_world_y; mousex += camerax; mousey += cameray;
I wanted to solve this so bad I made an example proggie. Here ya go!
IsoMap.7z Binary, source, and data. 7-zip (archiver program for 7z files).
Obligatory screenie :
{"name":"608177","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/7\/c\/7c55485273d058cca25e2de1b1af8b16.png","w":812,"h":632,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/7\/c\/7c55485273d058cca25e2de1b1af8b16"}
And the full source code :
At 0,0 gives me 7,-7.
Well, judging from the picture, (0,0) on the screen does seem likely to be at (7; -7) in isometry...
If you draw it like this:
for(int j = 0;j < this->total_tiles;j++) { this->tile_x = (j * (this->tile_w / 2)) + (i * (this->tile_w / 2)); this->tile_y = (i * (this->tile_h / 2)) - (j * (this->tile_h / 2)) - this->tile_h/2; }
(0; 0) should show (0; 0) for you...
@Edgar, Thank you! Will check it with more time tonight.
@Aikei_c thanks but it still gives me 7,-7
I cleaned it up a bit and changed the dimensions and added in a camera with the arrow buttons.
Here's an updated exe and src (Needs the data and dlls from the earlier attachment)
Here's an updated exe and src (Needs the data and dlls from the earlier attachment)
{"name":"608181","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/7\/1\/71cf32f7b6d8da2604b3d5371e28862d.png","w":812,"h":632,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/7\/1\/71cf32f7b6d8da2604b3d5371e28862d"}
Edgar, the problem is your code is A5 and mine A4, thank you anyway.
I give up for now, eventually I will start everything from scratch in A5
Thanks everyone.
The logic should still remain the same, doesn't matter if it's allegro 4 or 5. Regardless, going with allegro 5 instead of 4 is a good idea.
The formulas and conversion are the same. I never meant to suggest you had to switch to A5. Don't you already have something working in A4? Feel free to continue it.
I really only wrote the demo to demonstrate that my system works.
I'm afraid you must be trying to just paste our code into your project, while you need to understand what is going on under the hood. Try to understand what people here told you, maybe do some drawings (and calculations) on paper to help you understand what's going on. That will be so much better than just taking someone else's code literally and hoping it's gonna work.
I'm afraid you must be trying to just paste our code into your project, while you need to understand what is going on under the hood. Try to understand what people here told you, maybe do some drawings (and calculations) on paper to help you understand what's going on. That will be so much better than just taking someone else's code literally and hoping it's gonna work.
It's exactly the other way around, I don't have any interest on get the code working without understand its logic.
Otherwise I would take Edgar's code and start my project from there.
One thing I didn't say is that you could probably realign 0,0 on the map to be in the top middle. You would have to redo the calculations a bit but then you wouldn't have to invert the y.
What part are you having trouble with? Here are the formulas again, for reference. (This is after having aligned with 0,0 on your iso map).
Edgar, there is something else besides a map positioning / camera issue.
Even when I tried a lot of different approach the isometric numbers never match with the amount of tiles per row/column.
Got busy with something else right now, but when I have some time I will start it from scratch in A5, then I will look again at your code and will let you know.
Thank you.