Rendering & SDL

Started by
2 comments, last by rip-off 16 years, 2 months ago
Hey again, When you blit a SDL_Surface in SDL the content of the source SDL_Surface gets cleared. I tried to duplicate the SDL_Surface but it doesn't work (as shown in the code below). The purpose of this is that the program should only need to draw the room/level once, and not everytime it loops. The SDL wiki states that you shouldn't use memcpy (which I tried at first, but it segfaulted ofc) and recommended the method I used below as the proper way. Any suggestions?

Hero hero(200, 400);
SDL_Surface *levelm;
SDL_Surface *levels;
bool update_level;

void InitRender(SDL_Surface *screen)
{
      levels = SDL_SetVideoMode(screen->clip_rect.w, screen->clip_rect.w, 16, SDL_SWSURFACE | SDL_PREALLOC);                            
      levelm = SDL_SetVideoMode(screen->clip_rect.w, screen->clip_rect.w, 16, SDL_SWSURFACE | SDL_PREALLOC);
      update_level = true;
}

void RenderScene(SDL_Surface *screen, SDL_Surface *newscreen, SDL_Surface *emptyscreen, Room *rooms, int croom)
{                                 
        /* Prepare scene */
        SDL_SetColorKey(newscreen, SDL_SRCCOLORKEY, SDL_MapRGB(newscreen->format, 0x00, 0x00, 0x00)); 
        SDL_FillRect(SDL_GetVideoSurface(), NULL, SDL_MapRGB(SDL_GetVideoSurface()->format, 0,0,0));     
        
        /* Draw into scene */
        if (update_level == true)
        {
           rooms[croom].Draw(levelm);
        }
        else
        {
                  levelm = levels;
        }   
        levels = levelm;     
        levels->refcount++;       
        update_level = false;        
        SDL_BlitSurface(levelm, &levelm->clip_rect, newscreen, &newscreen->clip_rect);
        hero.Draw(newscreen);
        
        /* Render scene */        
        SDL_BlitSurface(newscreen, NULL, screen, NULL);
        SDL_Flip(screen);      
}
Advertisement
The source doesn't get cleared. Can you link me to where you read that it does.

From the looks of your code you have a skewed understanding of how to render things in SDL. At one point you have a function that takes a "screen" pointer as an argument and then calls SDL_SetVideoMode repeatedly. Calling SDL_SetVideoMode more than once will deallocate the current video surface (screen, followed by levels will be bad pointers). If you post a more complete example, I may be able to re-write it slightly better.

To duplicate a surface - something you rarely have to do - look into SDL_CreateRGBSurface(). But there is a way around this.
Quote:
The source doesn't get cleared. Can you link me to where you read that it does.


Try it yourself. Draw something into a surface, blit it, then blit again. Voila, voidness!

Quote:
From the looks of your code you have a skewed understanding of how to render things in SDL. At one point you have a function that takes a "screen" pointer as an argument and then calls SDL_SetVideoMode repeatedly. Calling SDL_SetVideoMode more than once will deallocate the current video surface (screen, followed by levels will be bad pointers). If you post a more complete example, I may be able to re-write it slightly better.


Please separate InitRender from RenderScene. InitRender executes only once before the game loop.

Quote:To duplicate a surface - something you rarely have to do - look into SDL_CreateRGBSurface(). But there is a way around this.


So, I'm supposed to only use one surface, excluding those that gets generated through SDL_LoadBMP and such, or what do you mean?

Quote:
Try it yourself. Draw something into a surface, blit it, then blit again. Voila, voidness!


I have used SDL for something like 4 years. I am very familiar with it, I've read some of the code. I know that blitting from a surface does not alter the pixel data of that surface.

If you post an small example of this, Ill run it and see what results I get. I'm always prepared to be proven wrong [smile].

Quote:
Please separate InitRender from RenderScene. InitRender executes only once before the game loop.


While I can see that, the fact that InitRender calls SDL_SetVideoMode() twice means that, at the very least, you have a single bad pointer (levels). You may have an additional bad pointer if the "screen" parameter points to something returned by SDL_SetVideoMode() too.

Quote:
So, I'm supposed to only use one surface, excluding those that gets generated through SDL_LoadBMP and such, or what do you mean?


Usually, yes. Of course there are exceptions.

Maybe you're trying to implement (software) double buffering? Parallax backgrounds? Sometimes you will need additional surfaces. If I had an idea of what all the different surfaces in your code were supposed to represent I might be able to explain a better way (If one exists [grin]).

I can see you modifying the refcount member of an SDL_Surface, which is possibly a bad idea.

This topic is closed to new replies.

Advertisement