Sign in to follow this  

Rendering Technique

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

If you intended to correct an error in the post then please contact us.

Recommended Posts

Looking around at other games...and a few websites here and there I've noticed a large difference in the way I draw tiles and the way everyone else draws tiles.... The first time i read Jim Adams' Introduction to isometric engines I was under the impression that you were supposed to draw your tile map like this: so...in this vein i created my tile map....which does exactly that. now since then I have seen others (everyone else) render their tile maps like this: Can one of you ISO pros shed some light on this for me. Which is better (probably the latter due to its popularity) and why? Thanks! [Edited by - nex7 on June 16, 2006 2:25:46 PM]

Share this post


Link to post
Share on other sites
My first iso engine was created in manner of your first example. It ran fine. But after half year of programming I had a BIG problem. When I tried to create a rectangular iso rooms I had to erase some areas from map, which led to non-optimal memory usage. Changes to new approach taked me a 3 week of my life[smile].
For example in second approach for erase a rectangular area on map, you do two 'for' loops. On first I had to do it with bunch of 'if'-s and similar.
Three lines of code for 2nd example and 70-80 lines of code for first. Which is simplier[smile]?
Also coordinate manipulation is much more easier for second than first example.

"Which is better (probably the latter due to its popularity)..."
If something is popular that doesn't mean that is good (better). [smile] In this case it is BETTER and that's reason why it is so popular :D

Share this post


Link to post
Share on other sites
The second view just confuses me..

Is there a good example on that type of rendering somewhere?

because that just screws up my head to try and think about scrolling around.

i mean when you go right...your going..down and right....sorta...

i know i just have to get the idea into my head but right now im stumped.

Share this post


Link to post
Share on other sites
even the math...if someone could post some scrolling and tile finding math for that view...

that would be great.

it just looks wierd...i mean really..who draws from right to left?

Share this post


Link to post
Share on other sites
For those of you reading the post who have made iso engines...do you use the first or second technique to render your tiles???

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
My twopenn'th: both are accurate for me. I render my tiles in the order described in the first image, but I actually store the tiles in the order described in the second image (assuming the top number's the x coord, and the bottom's the y) - that is, the tilemap is one big 2D array, which makes it easy to do all the internal game logic, etc.



Share this post


Link to post
Share on other sites
welp...over the weekend i was able to implement the diamond shaped tile map...im going to need a way to cull the non visible tiles but ill figure that out later.

the mouse mapping logic was a bit tricky but the tile plotting was a LOT easier than the staggered map.

Share this post


Link to post
Share on other sites
Going the diamond shape is by far the 'nicest' approach...if you use matrices for your view transforms.

If your tiles are 40*20, then you render them like this (pseudo-code):


viewmatrix = [[20, -20]
[10, 10]]

for ( x = 0; x < mapwidth; x++ )
{
for ( y = 0; y < mapheight; y++ )
{
p = [x, y]
p' = viewmatrix * p

blit( tile, p' )
}
}


A basic grasp of linear algebra is needed though.

Share this post


Link to post
Share on other sites
What would you do for larger maps...rendering all of mine would be bad...to say the least. My map is H U G E so I changed mine up to render a set number of tiles and just update which tiles are being rendered based on the screen offset position. The only problem i find is that i cant really have fine tile coords this way.

what i do now:

for( int y = 0; y< MapViewHeight; y++)
{
for(int x = 0; x< MapViewWidth; x++)
{
Tile t = Tiles[x + screenOffsetX, y + screenOffsetY];
DrawTile(t,x,y);
}

}

so i am rendering MapViewHeight * MapViewWidth tiles out of a large super set which is good for performance but i cant do fine map scrolling because it has to move by an entire tile.

So i need to find a way to draw the view section of the map the way it would be in worldspace so that i can move it by pixel instead of by tile.

did that make sense?

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Quote:
Original post by nex7
the mouse mapping logic was a bit tricky but the tile plotting was a LOT easier than the staggered map.


The mouse-to-tile mapping should be fairly straight forward (assuming you store your tiles as described in the second image in the original post - ie. as a standard 2D array). Just use the formulae given by Luctus, ie:

tile_x = (screen_y / tile_height) + (screen_x / tile_width)
tile_y = (screen_y / tile_height) - (screen_x / tile_width)

(I converted from matrices.)

Screen_x & Screen_y need to be the pixel location of the point you're converting, relative to the origin of the tile-map (ie. the top point of the diamond in the second picture). So you have to take into account any scrolling, basically.

Yeah, drawing the whole map will be too slow. Just draw the tiles that are going to be on screen. This is pretty easy to calculate in this example. Use the above formulae to calculate the tile-map location of the upper-left and lower-right corners of the screen, and then draw the tiles in lines that are horizontal in screen-space - ie. diagonal in tile-space (so in your loop you'll have tilex++; tiley++; or something).

You have to offset every second row, and this offset is actually calculated based on the fractal part of the tile co-ordinates of the upper-left corner of the screen. Mess about and you'll see what I mean.

Sorry this is confusingly written - it's actually all fairly simple stuff. I wrote a little C# app that renders a tilemap (in tile-space) and shows the screen (in tilespace - so it's a sort of big, distorted diamond) and messed about with my logic there until it was right, before putting it into the game engine to render normally. That helped heaps.


Share this post


Link to post
Share on other sites
Yeah have everything working now...the mouse picking and tile rendering all works correctly, the only thing im missing is grabbing the screen rect out of my world array.


I have a 2d array...fairly standard....and i want to grab the screen rect out of the world space....

also normally you start drawing at 0,0....in this situation you cant do that...In my situation I have to start drawing directly north from the middle of my screen so that the edges of the diamond dont show up on the screen.

im sure i'm thinking about it wrong...and i just need to calculate where that tile would be in screen space given that formula....but im not quite there yet

as it stands i would never see the corners of my map...because i always draw my map as a 20x20 diamond and just switch out tiles based on location.

Share this post


Link to post
Share on other sites
I feel... How you like to draw your ISO Map depends on How you like to represent the game(I method - Staggered or II Method - Diamond) .

For example in my

Isometric Engine
I use staggered Map. Since I want to make games like Jagged Allaince 2, I don't like to display empty blanks on the four sides of my Map.

But for my
Isometric Thief Game I have used Diamond (II Method) map, and it suits the type of setting for the game.

Which method is best?... Dunno... personally I prefer the 1st method :)

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Quote:
Original post by nex7
anyone have an example of how to get a screenrect worth of tiles out of an array for a diamond tilemap?


This is a bit of a rough cut-n-paste from a C# project that I have here (my proper C++ code isn't here, I'm afraid). It's pretty messy, but maybe it will help. Basically what I do is:

1. Calculate the extents of the screen (stored in screenPoints), in tilespace.
2. Do some minor adjustments to the start tile (ie. the upper-left one) based on the screen's sub-tile location.
3. Draw the tiles, left to right, top to bottom, as you'd expect.

The obscurely-named bShiftX variable effectively determines whether, on moving to the next row of tiles, they are offset to the left (onscreen) or right of the row above (ie. in your first image up at the top there, at the end of the first row bShiftX would be false because going from tile 0 to tile 5 would - in my diamond tilemap - be an increment in the Y coordinate).

Confusing and poorly written I know, but maybe will help you a bit.



// Calculate the 'visible' tiles.
double x1, y1;
double x2, y2;
double x3, y3;
double x4, y4;

// Transform screen corners into tilespace.
x1 = screenPoints[0].X + adjustx;
y1 = screenPoints[0].Y + adjusty;
x2 = screenPoints[1].X + adjustx;
y2 = screenPoints[1].Y + adjusty;
x3 = screenPoints[2].X + adjustx;
y3 = screenPoints[2].Y + adjusty;
x4 = screenPoints[3].X + adjustx;
y4 = screenPoints[3].Y + adjusty;

double fracx1 = x1 - Math.Floor(x1);
double fracy1 = y1 - Math.Floor(y1);

double fracx2 = x2 - Math.Floor(x2);
double fracy2 = y2 - Math.Floor(y2);

// Height and width of screen, in tiles.
int nScreenRowWidth = (int)x2 - (int)x1 + 1;
int nScreenColHeight = ((int)x1 - (int)x4 + 1) * 2;

// Based on sub-tile location of screen-rectangle, might have to
// draw a very slightly different set of tiles.
bool bShiftX = true;
bool b1, b2;
b1 = (fracx1 + fracy1) > 1.0;
b2 = fracx1 > fracy1;

if (!b1 && b2)
{
y1 -= 1.0;
bShiftX = false;
}

if (b1 && !b2)
{
bShiftX = false;
}

if (b1 && b2)
{
x1 += 1.0;
bShiftX = true;
}

// Draw the tiles.
for (int j = 0; j < nScreenColHeight; j++)
{
x = (int)Math.Floor(x1);
y = (int)Math.Floor(y1);
for (int i =0; i < nScreenRowWidth; i++)
{
/* DrawTile(x * tileWidth, y * tileHeight) */
x++;
y++;
}

x1 -= bShiftX ? 1.0 : 0.0;
y1 += bShiftX ? 0.0 : 1.0;
bShiftX = !bShiftX;
}


Share this post


Link to post
Share on other sites

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

If you intended to correct an error in the post then please contact us.

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