Agggh!!! Slow FPS drawing map [Solved]

Started by
10 comments, last by kiketom 18 years, 1 month ago
Hi!! I have a FPS problem blitting my map structure to screen. I define the screen buffer:

/* in main.cpp */
screen = SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, 24, SDL_HWSURFACE | SDL_DOUBLEBUF);


/* And this is the Blitting proccess */
/* in Layer.cpp */

int cols;
int rows;
	
	for (int ii = 0; ii <= this->vectorTiles.size() - 1; ii++)
	{
	    cols = (ii % this->GetColsLayer());
            rows = (ii / this->GetRowsLayer());

	    PlotX = (cols*TILE_WIDTH/2)-(rows*(TILE_WIDTH/2));
	    PlotY = ((rows*(TILE_HEIGHT/2))+(cols*(TILE_HEIGHT/2)));
			
			SDL_Rect rect_dest;
			rect_dest.w = 0;
			rect_dest.h = 0;
			rect_dest.x = PlotX;
			rect_dest.y = PlotY;

			if ((PlotX  >= rect->x)&&(PlotX <= rect->x+rect->w)&&(PlotY + TILE_HEIGHT >=rect->y)&&(PlotY<=rect->y+rect->h))
			{
				
				indexImage = this->vectorTiles[(rows * this->GetColsLayer()) + cols]->GetImageNumber();
				
				SDL_Surface *imageTile = this->TileSet->GetTile(indexImage);
				SDL_BlitSurface(imageTile, NULL, screen, &rect_dest);
				SDL_FreeSurface(imageTile);
			}

}



This is the result!! [wow] 12 FPS with only 3 frames!! Where is the problem????? [depressed] Thx [Edited by - kiketom on March 16, 2006 9:13:19 AM]
Tomy
Advertisement
Are you creating a new SDL_surface every time you call TileSet.GetTile()? If you are creating and freeing surfaces per frame, then that's your bottleneck.
I dont know much about SDL, but.


//If this line loads surface
SDL_Surface *imageTile = this->TileSet->GetTile(indexImage);

//and this line deletes the surface
SDL_FreeSurface(imageTile);

then that is your problem.

you should never load and delete images within your main drawing loop,

instead load your images at game start (or level start) and use them until the game is over (or level changes)

loading and freeing images for each tile is extreamly wasteful

Raymond Jacobs, Owner - Ethereal Darkness Interactive
www.EDIGames.com - EDIGamesCompany - @EDIGames

I'm not loading the image from File every time.
I'm getting part of the image from the imageTile loaded.



SDL_Surface* tileSet::GetTile(int Index){    Uint32 rmask, gmask, bmask, amask;    	#if SDL_BYTEORDER == SDL_BIG_ENDIAN	    rmask = 0xff000000;	    gmask = 0x00ff0000;	    bmask = 0x0000ff00;	    amask = 0x000000ff;	#else	    rmask = 0x000000ff;	    gmask = 0x0000ff00;	    bmask = 0x00ff0000;	    amask = 0xff000000;	#endif    		SDL_Surface *surface = SDL_CreateRGBSurface(SDL_HWSURFACE | SDL_SRCCOLORKEY, this->getWidthImageTiles(), this->getWidthImageTiles(), 32, rmask, gmask, bmask, amask);		SDL_Rect rect_origen;	rect_origen.w = this->getWidthImageTiles();	rect_origen.h = this->getHeightImageTiles();	rect_origen.y = (Index / this->getImageCols()) * rect_origen.h;	rect_origen.x = (Index % this->getImageRows()) * rect_origen.w;			SDL_BlitSurface(this->m_image_tiles, &rect_origen, surface, NULL);		return surface;	}
Tomy
It looks like you are calling SDL_CreateRGBSurface per tile per frame. Even if you're not loading anything from disk, this is going to be very slow. :)
Orin Tresnjak | Graphics ProgrammerBethesda Game StudiosStandard Disclaimer: My posts represent my opinions and not those of Bethesda/Zenimax, etc.
You are still creating new memory and deleting the memory every frame due to SDL_CreateRGBSurface...

Maybe you can cache the surfaces in the beginning and then just return the cached surfaces...
Quote:Original post by kiketom
I'm not loading the image from File every time.
I'm getting part of the image from the imageTile loaded.



*** Source Snippet Removed ***


Lo que estas haciendo es crear una imagen nueva cada vez que dibujas un tile, y despues volverla a borrar. Usas esa imagen para copiar en ella el grafico del tile, y despues volver a copiar de ahi a la pantalla.

Por que no dibujas el tile directamente desde la imagen que tiene todos los tiles (el tileset, vamos) a la pantalla?

De esta manera te ahorras el crear y destruir cientos de superficies cada fotograma, que es lo que te esta bajando la velocidad.

Simplemente:

SDL_BlitSurface(TileSet->GetImageTiles(), &rect_origen, screen, &rect_dest);

Como los datos de la superficie m_image_tiles y el rectangulo de origen se calculan en TileSet, un mejor disenyo seria incluir esto en el propio TileSet, algo como un metodo drawTile (screen, &rect_dest, indiceTile)

Espero que te ayude, un saludo.

PD: I write this in spanish as your profile says you're from spain. If you aren't, just say so and I'll translate ;)
-----DevZing Blog (in Spanish)
OK, gracias voy a probar
;)
Tomy
Now the FPS are 17.
[oh]

still this is very slow ........
Tomy
Quote:Original post by kiketom
Now the FPS are 17.
[oh]

still this is very slow ........


Un par de ideas rapidas:

- Prueba a ejecutarlo a pantalla completa, a ver si el resultado es distinto

- Crea las superficies del tileset con el mismo formato de pixel que la superficie screen, esto evitara que el sistema tenga que hacer conversiones en cada blit


De todos modos, es posible que el problema no este en el codigo este, sino en alguna otra cosa que tu programa haga y que pueda estar causando el cuello de botella.

-----

A couple of fast ideas:

- Try running it in fullscreen, and see if you get different rates

- Create the tileset surfaces using the same pixel format than the screen surface, this should stop the system from performing conversions in every blit


Anyways, it's possible the problem is not in this code, but in some other thing your program is doing and creating that bottleneck.
-----DevZing Blog (in Spanish)

This topic is closed to new replies.

Advertisement