Positioning iso tiles

Started by
6 comments, last by cryo75 15 years, 8 months ago
Hi all, I'm building an iso tile engine similar to aoe2 and civ3... but am still soooo far away!! :) I'm using c# and xna. Anyway, I got a basic engine which loads tiles and displays them. The problem is that the tiles are not be positioned adjacent to each other. It looks like a chess board with black areas representing that no tile is being place there. This is the current drawing code: for (int x = 0; x < tileMapWidth; x++) { for (int y = 0; y < tileMapHeight; y++) { int textureIndex = map[y, x]; Texture2D texture = tileTextures[textureIndex]; batch.Draw(texture, new Rectangle(x * tileWidth - (int)camera.Position.X, y * tileHeight - (int)camera.Position.Y, tileWidth, tileHeight), Color.White); } } Any ideas, Thanks, cryo
Advertisement
You need to account for that the rows goes diagonally in an isometric tilemap.

First of all, you need to consider that you should have two sets of coordinates; world- and screen-coordinates. The world coordinates specify where on the tile map you are, e.g. (3,2) would mean the third row of tiles, second column. The screen-coordinates is where on the screen your tiles are drawn.

Now, if you put a tile at (0,0) in world-space, it would intuitively end up at (0+camera.x, 0+camera.y) on the screen, right? If you put a second tile at (1,0), logically it should end up diagonally relative to the first:
 __ __(0,0)| / \ ||/  _\|__(1,0)|\ | /|\ ||_\|/_| \|   |\   /|   |_\ /_|

We see that it should be at (1*(tile.width/2) + camera.x, 1*(tile.height/2) + camera.y). One step along world-x moves it tile.width/2 to the right and tile.height/2 down. Putting another one at (0,1):
       __ __(0,0)      | / \ |    _ |/  _\|   | /|\ | /|   |/ |_\|/_|   |\   /|   |_\ /_| (0,1)

It should end up at (1*(-tile.width/2) + camera.x, 1*(tile.height/2) + camera.y). This time, one step along world-y moves it tile.width/2 to the left and tile.height/2 down.

Making an educated guess and combining those two, we can generalize this for any coordinate in world coordinates (x,y) to screen coordinates (x',y').

/* One (tile.width/2) step to right on screen for each step along world-x, and  * one (tile.width/2) step to the left for each step along world-y, then  * adjust for camera. */x' = x*(tile.width/2) - y*(tile.width/2) + camera.x /* One (tile.height/2) step down on screen for each step along world-x, and one  * (tile.height/2) step down for each step along world-y, then adjust for camera. */y' = x*(tile.height/2) + y*(tile.height/2) + camera.y


You usually also want to be able go the other way, from screen coordinates to world coordinates. For example, if you want to know on which tile the player clicked with the mouse. It's a bit more involved explaining how that works, so I'm just going to give you the formula:

x = (x'-camera.x)/tile.width + (y'-camera.y)/tile.heighty = -(x'-camera.x)/tile.width + (y'-camera.y)/tile.height


[Edited by - Luctus on August 18, 2008 12:36:57 PM]
-LuctusIn the beginning the Universe was created. This has made a lot of people very angry and been widely regarded as a bad move - Douglas Adams
This is the new drawing routine:

int tileMapWidth = map.GetLength(1);
int tileMapHeight = map.GetLength(0);

for (int x = 0; x < tileMapWidth; x++)
{
for (int y = 0; y < tileMapHeight; y++)
{
int textureIndex = map[y, x];
Texture2D texture = tileTextures[textureIndex];

int screenX = x * (tileWidth / 2) - y * (-tileWidth / 2) - (int)camera.Position.X;
int screenY = x * (tileHeight / 2) + y * (tileWidth / 2) - (int)camera.Position.Y;

batch.Draw(texture,
new Rectangle(screenX, screenY, tileWidth, tileHeight),
Color.White);
}
}

And the effect can be seen here...

http://www.debonosoft.com/files/isomap.jpg

Any ideas?

Thanks,
cryo
I changed the formulas to:

int screenX = x * tileWidth - (y % 2) * tileHeight - (int)camera.Position.X;
int screenY = y * (tileHeight / 2) - (int)camera.Position.Y;

And it works fine now.

cryo
Quote:Original post by cryo75
int screenX = x * (tileWidth / 2) - y * (-tileWidth / 2) - (int)camera.Position.X;
You have a double negative on this row, change one of them to a +.

-LuctusIn the beginning the Universe was created. This has made a lot of people very angry and been widely regarded as a bad move - Douglas Adams
I'm using these formulas to draw the iso tiles:

int screenX = x * tileWidth + (y % 2) * tileHeight - (int)camera.Position.X;
int screenY = y * (tileHeight / 2) - (int)camera.Position.Y;

And they work fine!

Now I add the opposite formulas to get the current tile the mouse is on. I tried these but won't work:

cellX = (int)(mx - (int)camera.Position.X) / TileLayer.TileWidth + (my - (int)camera.Position.Y) / TileLayer.TileHeight;
cellY = (int)-(mx - (int)camera.Position.X) / TileLayer.TileWidth + (my - (int)camera.Position.Y) / TileLayer.TileHeight;


Any ideas?

Regards,
cryo
First of all, if you're subtracting the camera position when converting to screen-coordinates, you can't subtract them again when converting back to world-coordinates.

But most importantly
int screenX = x * tileWidth + (y % 2) * tileHeight - (int)camera.Position.X;int screenY = y * (tileHeight / 2) - (int)camera.Position.Y;

isn't the same as
x' = x*(tile.width/2) - y*(tile.width/2) + camera.x y' = x*(tile.height/2) + y*(tile.height/2) + camera.y

so naturally, using the inverse I gave you won't work.
-LuctusIn the beginning the Universe was created. This has made a lot of people very angry and been widely regarded as a bad move - Douglas Adams
Your original formula for placing iso tiles was not working and I had to alter it (after doing some searching).

Now I need to convert back screen coords to world coords!! :)

This topic is closed to new replies.

Advertisement