function be made more efficient?
Can my function be made more efficient? I have am map 20x100,tilesize 32, windows size of 640x480.
When i call this function it significantly reduces the fps by 1/3.
DrawMap(SDL_Surface * dest)
{
int first_block_x = (int)(camera_x/TILESIZE);
int last_block_x = (int)(camera_x/TILESIZE)
+(SCREEN_WIDTH/TILESIZE);
int first_block_y = (int)(camera_y/TILESIZE);
int last_block_y = (int)(camera_y/TILESIZE)
+(SCREEN_HEIGHT/TILESIZE);
camera_y-=0.4f;
for (int y = first_block_y; y<=last_block_y; y++)
{
for (int x = first_block_x; x<=last_block_x; x++)
{
for(int i =0; i<TOTALTILES; ++i)
{
if (Map[y][x] == i)
tilesheet.Draw(dest, (float)(x*TILESIZE)-camera_x,
(float)(y*TILESIZE)-camera_y,&tile );
}
}
}
}
Why do you need to test all tile values and see if they are equal to the value in your map. Why not instead just use the value of the map as the tile to draw....
&tile[(Map[y][x])] or so...
If you have an "invalid" value than you can use something like if(Map[y][x]!=INVALID_VALUE) but don't loop through all of your tile values like that because your doing a ton of looping....
Also I know I am nitpicking but do you really need to repeat calculations for last_block that you do in first_block? last_block is based on first_block so why not like:
int last_block_x = first_block_x + (SCREEN_WIDTH/TILESIZE)
&tile[(Map[y][x])] or so...
If you have an "invalid" value than you can use something like if(Map[y][x]!=INVALID_VALUE) but don't loop through all of your tile values like that because your doing a ton of looping....
Also I know I am nitpicking but do you really need to repeat calculations for last_block that you do in first_block? last_block is based on first_block so why not like:
int last_block_x = first_block_x + (SCREEN_WIDTH/TILESIZE)
Ignoring most time-complexity terminology, your for-loop is lacking optimization and will have a very bad worst-case and a mediocre average case. I would suggest that rather than iterate through each tile sheet index for every single map location you do what Basement24 is suggesting and use the value at your map x and y location to represent which index in the tile sheet to draw.
DrawMap(SDL_Surface * dest)
{
int first_block_x = (int)(camera_x/TILESIZE);
int first_block_y = (int)(camera_y/TILESIZE);
int last_block_x = first_block_x + (SCREEN_WIDTH/TILESIZE);
int last_block_y = first_block_y + (SCREEN_HEIGHT/TILESIZE);
//camera_y-=0.4f;
for (int y = first_block_y; y<=last_block_y; y++)
{
for (int x = first_block_x; x<=last_block_x; x++)
{
if(Map[y][x]<12)
tilesheet.Draw(dest, (float)(x*TILESIZE)-camera_x,(float)(y*TILESIZE)-camera_y,&tile[(Map[y][x])]);
}
}
}
ok I did what you say,shadowisadog. But my fps it still reduced by 1/3 could the be any other problem?
{
int first_block_x = (int)(camera_x/TILESIZE);
int first_block_y = (int)(camera_y/TILESIZE);
int last_block_x = first_block_x + (SCREEN_WIDTH/TILESIZE);
int last_block_y = first_block_y + (SCREEN_HEIGHT/TILESIZE);
//camera_y-=0.4f;
for (int y = first_block_y; y<=last_block_y; y++)
{
for (int x = first_block_x; x<=last_block_x; x++)
{
if(Map[y][x]<12)
tilesheet.Draw(dest, (float)(x*TILESIZE)-camera_x,(float)(y*TILESIZE)-camera_y,&tile[(Map[y][x])]);
}
}
}
ok I did what you say,shadowisadog. But my fps it still reduced by 1/3 could the be any other problem?
As has been said twice, you have a very odd implementation in the middle of your loop and should really try to grasp what shadow told you because it avoids a TON of looping (number of tiles * tiles wide * tiles high).
But another point is, what does "reduces the fps by 1/3" mean? And compared to what? If you were drawing nothing and it was running at 600fps and now you're drawing the screen and it runs at 400fps that's no big deal.
But another point is, what does "reduces the fps by 1/3" mean? And compared to what? If you were drawing nothing and it was running at 600fps and now you're drawing the screen and it runs at 400fps that's no big deal.
Are you using any kind of hardware acceleration? I don't think SDL alone does this, and that would probably reduce your fps a bit (I don't think you'd be going that low unless your CPU is archaic tho). Also, you say your map is 20x100 tiles, well that's 2,000 tiles you're drawing separately. I'm not sure if this is something you want to be considering yet but you could significantly increase performance (relative to what you've got) if you implemented some sort of batching for the tile sheet's Draw method.
Since you've got 20x100 tiles, each at 32 pixels wide, you're looking at a standard map resolution of 640x3200. That's quite a bit larger vertically than your window size, you could do a little bit of math and find out what tiles are even within your window and only draw those.
Lastly, you say that you know that your FPS is reduced by 1/3 because you have it "capped" to 32 frames per second. How exactly are you regulating this? I don't *think* SDL offers this functionality directly, and that leads me to believe you may have some sleep() calls in your code somewhere. If this isn't done properly I could easily see that being the culprit as well.
Since you've got 20x100 tiles, each at 32 pixels wide, you're looking at a standard map resolution of 640x3200. That's quite a bit larger vertically than your window size, you could do a little bit of math and find out what tiles are even within your window and only draw those.
Lastly, you say that you know that your FPS is reduced by 1/3 because you have it "capped" to 32 frames per second. How exactly are you regulating this? I don't *think* SDL offers this functionality directly, and that leads me to believe you may have some sleep() calls in your code somewhere. If this isn't done properly I could easily see that being the culprit as well.
This function is good enough. Look elsewhere.
You said you capped the framerate.
SDL_Delay is not perfect. You might ask for 1ms and it takes 12. The granularity varies from platform to platform.
From the manual: "It waits at least the specified time, but possible longer due to OS scheduling. The delay granularity is at least 10 ms. Some platforms have shorter clock ticks but this is the most common."
I'll bet that's a large part of the problem. As for the drawing, its the actual drawing that takes the time, not this cycler function. SDL CAN use hardware acceleration; its simply a wrapper library for other systems that do.
However you have to make sure its fed good data and knows what to do.
You have to make sure your tile images are in the same format as the destination surface, for starters.
Look up SDL_DisplayFormat and SDL_DisplayFormatAlpha.
If you're using color key, you can activate RLE acceleration with SDL_ConvertSurface and the SDL_RLEACCEL flag. Also look into SDL_HWACCEL (for surfaces that are blit) and SDL_HWSURFACE (for everything).
Basically, you're just making sure that there aren't any roadblocks to letting SDL use hardware acceleration.
There are more possibilities, like memory alignment, but if you run data through display format, aren't using 24 bits per pixel mode (instead of 32) and are letting SDL allocate memory for you, that's probably not an issue for you.
You said you capped the framerate.
SDL_Delay is not perfect. You might ask for 1ms and it takes 12. The granularity varies from platform to platform.
From the manual: "It waits at least the specified time, but possible longer due to OS scheduling. The delay granularity is at least 10 ms. Some platforms have shorter clock ticks but this is the most common."
I'll bet that's a large part of the problem. As for the drawing, its the actual drawing that takes the time, not this cycler function. SDL CAN use hardware acceleration; its simply a wrapper library for other systems that do.
However you have to make sure its fed good data and knows what to do.
You have to make sure your tile images are in the same format as the destination surface, for starters.
Look up SDL_DisplayFormat and SDL_DisplayFormatAlpha.
If you're using color key, you can activate RLE acceleration with SDL_ConvertSurface and the SDL_RLEACCEL flag. Also look into SDL_HWACCEL (for surfaces that are blit) and SDL_HWSURFACE (for everything).
Basically, you're just making sure that there aren't any roadblocks to letting SDL use hardware acceleration.
There are more possibilities, like memory alignment, but if you run data through display format, aren't using 24 bits per pixel mode (instead of 32) and are letting SDL allocate memory for you, that's probably not an issue for you.
Ok i did some testing and it seem as though my cap method was causing problem,what is the best method of calculating framerate?
Let dt the amount of time (in milliseconds) that has elapsed since the last time you checked framerate.
float framerate = 1000.f / float(dt);
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement