# Positioning iso tiles

This topic is 3438 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

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

##### Share on other sites
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]

##### Share on other sites
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

##### Share on other sites
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

##### Share on other sites
Quote:
 Original post by cryo75int 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 +.

##### Share on other sites
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

##### Share on other sites
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.