Archived

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

brewknowc

Iso Optimization

Recommended Posts

Hi, i recently started changing over my square tile-based game into an isometric tile game and am running into a few difficulties. I finally got the rendering/mouse mapping working, but am having trouble optimizing the rendering so that i''m not blitting too much offscreen. I went out and bought Pazera''s Iso book, but don''t understand some little things. Just to get the rendering working I was blitting every tile in my 50x60 tile map. (about 3000 blits per frame!) I noticed how slow this was already even on my 500mhz system. There''s a section in the book on how to optimize this, but for diamond shaped maps I don''t understand how I am supposed to blit from west to east (left to right) when all my tiles'' x coordinates increase diagonally? Just as a test I put something like: // if tile is on the screen then blit it if((tile.x > -64)&&(tile.x < SCREEN_WIDTH)&& (tile.y > -32)&&(tile.y < SCREEN_HEIGHT)) blit tile This works alot better (blitting about 280 tiles/frame), but still seems like the loop itself is inefficient. If anyone can explain Pazerra''s optimization for diamond maps, that would be great, or even if you know other ways i can optimize the rendering. Thanks Alot BC - Free Your Mind -

Share this post


Link to post
Share on other sites

void CMapView::Draw()
{
SDL_Rect rect;
SDL_Surface *tile;

int x, y;

// Get the coordinates of the upper left tile
GetCellCoordinates((int)(MapX), (int)(MapY), &x, &y);

int screen_x = (x << 5) - (y << 5) - 32 - (int)(MapX);
int screen_y = (y << 4) + (x << 4) - (int)(MapY);

// To avoid jagged edges start drawing one tile up and to the left
x--;
screen_x -= 32;
screen_y -= 16;

int orig_x = x;
int orig_y = y;

int orig_screen_x = screen_x;

int row = 0;

SDL_FillRect(Buffer, NULL, 0);

while(screen_y < ScreenHeight)
{
while(screen_x < ScreenWidth)
{
if((x >= 0) && (y >= 0) && (x < Map.GetWidth()) && (y < Map.GetHeight()))
{
rect.x = screen_x;
rect.y = screen_y;
tile = Map(x, y)->Tile.GetCurrentFrame();
SDL_BlitSurface(tile, NULL, Buffer, &rect);
Map(x, y)->Tile.Update();
}
screen_x += 64;
x++;
y--;
}
row++;
screen_x = orig_screen_x + ((row & 1) << 5);
screen_y += 16;
orig_x += row & 1;
x = orig_x;
orig_y += 1 - (row & 1);
y = orig_y;
}
rect.x = X;
rect.y = Y;
SDL_BlitSurface(Buffer, NULL, Screen, &rect);
}



Ok this is the code I use. Essentialy I find out what tile is in the top left corner. Then I start drawing from left to right top to bottom on the screen. Note that when I do this I must move diagonally on the actual map. This way I never even check tiles that ar not on the screen.

This code is for diamond shaped maps, and works with smooth scrolling.

It may be hard to read because I have at least tried to optimize it any way I could. "x << 5" for example means is the same as "x * 32" and "x & 1" is the same as "x % 2" except they are much faster(and only works with numbers that are powers of 2).

[edited by - robinei on July 19, 2002 11:08:01 PM]

[edited by - robinei on July 19, 2002 11:18:14 PM]

[edited by - robinei on July 19, 2002 11:19:00 PM]

Share this post


Link to post
Share on other sites

I''m currently coding an isometric engine myself. Regarding this optimization thing, what I do is create a dirty tiles list. Dirty tiles means those that are visible and needs to be redrawn. Though my map is a two-dimensional array, the dirty tiles list is a simple linear list. As far as i can tell, this is a big help in the efficiency of my drawing code.

As for generating the list itself, it only needs to be done when the display state changes -- i.e., scrolling and panning, creatures moved/changed state, etc.

I''m trying to think of a way to make this faster still by simple pruning and adding to the dirty tiles list instead of generating the whole thing everytime it''s needed.

Share this post


Link to post
Share on other sites