Archived

This topic is now archived and is closed to further replies.

smooth scrolling an isometric map

This topic is 5102 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

Ok so i have my simple program that draws my isometric tiles to the screen but i am a little lost about how to convert from world space to screen space. I want to only draw the portions of the map that will be displayed. However im having trouble calculating which tile to begin with. This would be easy with a non isomtric just divide size by world psoition and there but this method needs some imporvement to work with iso tiles becauses one ppoint always falls in 2 tiles. is it best only to calculate even tiles or am i missinbg something and making this more difficult. Thancks

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
I am just started my first game using DirectX and found a scrolling solution for tiles (although it may not be optimal).

I use three DirectX surfaces:

primary
secondary
map

The secondary and primary surfaces are the same size as the screen, and are used to "flip" the map image to the screen without flickering. The map surface is the size of your entire map.

You can build the map surface by drawing your tiles on it. Then draw a clipped rectangle of the map surface to the secondary surface (in DirectX you can specify the source rectangle), and flip the secondary surface to the primary surface.

When the user clicks an arrow key you can move the bounds of the clipping rectangle and redraw the secondary surface.

Here is an excellent intro to DirectX for 2D games:
http://www.kuhnstall.de/tutorials/dx9sharp1.html

Share this post


Link to post
Share on other sites
you should go buy Ernest Pazera''s book "Isometric game programming with DirectX 7.0". it covers 3 types of tile maps extensively, going over how to manage screen vs. world space, how to do hit testing, how to manage what''s shown when, etc.

if you''re using DX9 or greater you''ll just need to read up on how to do 2D graphics in DX9 (start w/ID3DXSprite).

excellent book for isometric basics!

Share this post


Link to post
Share on other sites
I must say thank you for the help but i dont think i made my problem clear enough sorry for that.

What i want to know is how do i paint only a portioin of the map without looping through the whole array.

I thought that the best way to do this would be by getting the first tile in the top left corner and start looping at this
point and stop looping at the botom right. Thus drawind only
the needed part of the array and omiting everythin else.

This has been somewhat problematic and i think im making it more difficult than nesicary.

Share this post


Link to post
Share on other sites
Well it depends on what type of iso map your using (there are three ways to draw Iso maps). As Jeffzi said, get a copy of Ernest ''TANSTAAFL'' Pazera''s book on Iso programming as that explains it all for DirectDraw.

Also have a look in the articles section of this site for this as I belive there is a few articles about it (I know there is on covering Height maps on the front page at the moment )

The information you gave does not help much as it does not say which of the three iso drawing techniques you are using - Staggered (drawing the iso grid as if it''s a normal sqaure grid), Slanted (where each row is indented from the previous row) and Diamond (like it''s name sugests your taken the 2d grid and are drawing the tiles on the isometric plane as if it''s a square grid). Without know ing the exact information about the way your drawing your tile we can not help you, sorry.

When I find my code in tons of trouble,
Friends and colleages come to me,
Speaking words of wisdom:
"Write in C."

Share this post


Link to post
Share on other sites


If you can see the above picture (which will disappear in a month or so, as per Nervo's image hosting rules ), imagine that what you can see on screen at some given moment is indicated by the greyed box. The area you must draw is indicated by the numbered tiles, as those are the tiles that the box can intersect with depending on where the center of the screen is located within a given tile. If you know the location at which the view is centered, you can calculate the location which the upper left hand corner of the screen corresponds to within the tile map. Then, you can draw the rows as numbered, proceeding across the screen and downward.

From the starting tile (upper left hand corner), you would draw across N tiles (where N is the number of tiles across the view area), increasing x by +1 and decreasing y by -1 for each tile in the row, and adding TILE_DRAWING_WIDTH to the screen x coordinate. To move down a row, you add +1 to x. For this row, you only draw N-1 tiles, again incrementing x and decrementing y as you progress along the row. Then, to move to the third row, you increment y by +1. Keep alternating this scheme until you have drawn the last row.

It all hinges on calculating the starting tile. By whatever means you use to translate screen coords to world coords, and vice versa, you calculate the tile for the upper left corner, then subtract 1 from that tile's x coordinate, to get the tile just above and to the left of it. To calculate the number of tiles to draw per row (N), divide the viewport width in pixels by the TILE_DRAWING_WIDTH of a diamond tile, then add 1 for good measure. To get the number of rows to drawn down the screen, divide the viewport height in pixels by the TILE_DRAWING_HEIGHT/2, then add 1 (or more) for good measure, to ensure that tiles that own a very tall wall or object will be drawn so that the top of that object will be seen in the bottom of the viewport if necessary. You may have to play with these viewport sizes to suit your needs, for instance shortening a bit in the y direction if you plan to include a bottom of the screen panel, etc...

In my game, I perform two rendering passes; the first pass renders the floor, and the second pass renders any objects on the tiles. This allows sprites to straddle tile edges without being overwritten by subsequent tile floors.

EDIT: Note, this technique assumes that your maps is organized as a standard 2D array, which just happens to b turned by 45 degrees; ie, that if you could see the entire map on the screen, it would be a big diamond shape. Y increases down and to the left, x increases down and to the right, etc...

Josh
vertexnormal AT linuxmail DOT org


Check out Golem: Lands of Shadow, an isometrically rendered hack-and-slash inspired equally by Nethack and Diablo.

[edited by - VertexNormal on December 21, 2003 1:19:03 PM]

Share this post


Link to post
Share on other sites
Smooth scrolling is pretty simple. Another method of drawing maps is to work your way across and down drawing the tiles as you loop.
   
Across
_________\
D | /
o |
w |
n |
\|/

What you want to do is decide how many tiles will fit across and how many will fit going down, then loop those amounts drawing the world as you go. Doing this, you will only draw a section of the map.

For example, if you can only fit 20 across and 10 going down then you will only draw 200 tiles and not 100*100 (if that was the size of your map). To implement scrolling you need two variables, one that increments the horizontal scroll counter and another for the vertical scroll counter.

Then when you are drawing the map the start tile (thus implementing scrolling) will be the scroll value divided by tile size and pixel offset will be the modulus of the scroll value and the tile size. We alter the destination x,y based on this pixel offset.

Take for example if your tiles were 10 pixels wide. If the horizontal scroll value were represented by a or b:

10 20
___|__|
|a | b|
-------
|__|__|


If a = 2 and b = 13 then

2/10 = 0.2, 13/10 = 1.3

a_horiz_scroll = 0
a_xOff = 2

b_horiz_scroll = 1
b_xOff = 3

As you can see, this will give you pixel by pixel scrolling. The divide tells us which tile on the map we are on and the modulus tells us which pixel of that tile we are on, the amount left over.

Suppose I could fit 20x20 tiles on the screen then:

yTile = vertical_scroll_value / tile_height
xPixelOff = horizontal_scroll_value % tile_width
yPixelOff = vertical_scroll_value % tile_height

for y = 0 to 20 {
xTile = horizontal_scroll_value / tile_width
for x = 0 to 20 {
PutTile(x - xPixelOff, y - yPixelOff, Map[xTile][yTile])
xTile++
}
yTile ++
}





[edited by - Daerax on December 27, 2003 6:26:31 AM]

Share this post


Link to post
Share on other sites
I overlooked a few facts. Since this is an isometric game twice as many tiles will fit height wise because, every time it goes down a row it moves down half a tile; this is due to the diamond nature of the tiles. This same nature also requires that every odd row start half a tile to the right than the even rows. I also forgot to align the tiles into grids i.e PutTile(x * tile_width,...)

Here is the more accurate example:

yTile = vertical_scroll_value / tile_height
xPixelOff = horizontal_scroll_value % tile_width
yPixelOff = vertical_scroll_value % tile_height
py = 0

for y = 0 to 19 * 2 {
xTile = horizontal_scroll_value / tile_width

if y%2 != 0 then px = tile_width / 2 else px = 0
for x = 0 to 19 {
PutTile(px - xPixelOff, py - yPixelOff, Map[xTile][yTile])
xTile++
px+=tile_width
}
yTile ++
py += tile_height / 2
px = 0
}



[edited by - Daerax on December 27, 2003 10:29:23 AM]

Share this post


Link to post
Share on other sites