Sign in to follow this  
cryo75

Positioning iso tiles

Recommended Posts

cryo75    143
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 this post


Link to post
Share on other sites
Luctus    584
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.height
y = -(x'-camera.x)/tile.width + (y'-camera.y)/tile.height


[Edited by - Luctus on August 18, 2008 12:36:57 PM]

Share this post


Link to post
Share on other sites
cryo75    143
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 this post


Link to post
Share on other sites
cryo75    143
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 this post


Link to post
Share on other sites
Luctus    584
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 +.

Share this post


Link to post
Share on other sites
cryo75    143
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 this post


Link to post
Share on other sites
Luctus    584
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.

Share this post


Link to post
Share on other sites
cryo75    143
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!! :)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this