Page 1 of 2

Deleting surfaces in SDL

Posted: Wed Jan 14, 2009 1:54 pm
by Vortex
Hello, im sorry to inform that i bring you yet another noobish question
ive tryed so much but i cannot find a solution for this one :oops:

how do you in SDL remove surfaces without the program to start to bug?
i want like it to happen if an certain events happen exampel if the user presses the escape button i want a certain surface
to be removed from the screen so you cannot see it, when i try this the whole program freezes :cry:

Please help guys

Re: Deleting surfaces in SDL

Posted: Wed Jan 14, 2009 1:58 pm
by MarauderIIC
You can set a flag and stop drawing it*, or if you're not going to use it for a long time, you can use SDL_FreeSurface() to remove it from memory (but you can't draw something you've freed w/o it crashing, so be sure to not reference it. I'm not sure if setting it to NULL after doing a FreeSurface will avoid crashes or not).

*

Code: Select all

if (doDraw) {
    do a draw fn
}

Re: Deleting surfaces in SDL

Posted: Wed Jan 14, 2009 2:20 pm
by programmerinprogress
This is a rather simplistic solution, not sure it's what you want...

If you want to use the images again eventually, you could just keep them in memory, but come up with some way to prevent them drawing to the screen.

You could run some sort of boolean logic on them to prevent them from drawing, something like this...

Code: Select all


// this is the event part of your code 
switch(event.key.keysym.sym)
{
  case SDLK_RETURN: Is_Showing[Surface_Number] = (!Is_Showing[Surface_Number] );break;  
}

// this is your drawing part 
if(Is_Showing[Surface_Number])
{
   Apply_Surface(x,y,WhateverSurface,Screen,NULL) // this isnt the standard SDL drawing function, it's just a simplified one to demonstrate 
} 
If you havent already done so, you could get an SDL_Rect the size of the screen, and SDL_FillRect in your game cycle to Refresh the screen with a suitable colour.

The basic premise of this solution, is you treat your surfaces as if they were a load of light switches, on and off, you use the keyboard events to switch them on and off, thats what i'm trying to get at anyway.

I hope this was helpful, But try out Marauders solution if you want to actually remove the surfaces and not use them for a long time (although, if you wanted to use them straight away again, reloading the surfaces continuously might be a little wasteful)

Re: Deleting surfaces in SDL

Posted: Wed Jan 14, 2009 2:21 pm
by Vortex
thanks for your reply im experience a bit problems tough, now it still shows but it does not "animate" ( changes the frame or what its called ) and does not dissapear

Heres a bit of my code im experience trouble with:

Code: Select all

if ( menu == false )
{
               if( buttonSheet )
	{
	exitbutton.boxPos(-100000,-10000,0,0);
                SDL_FreeSurface( buttonSheet );
	buttonSheet = NULL;
	}
}


if ( menu == true )
{
if( ! buttonSheet )
{
       exitbutton.boxPos(( SCREEN_WIDTH - 80 ) / 2, 120,80,60);
       buttonSheet = load_image( "button.png" );
       exitbutton.show();
	
 }
}









Re: Deleting surfaces in SDL

Posted: Wed Jan 14, 2009 2:26 pm
by programmerinprogress
I mentioned you could refresh the screen and just add what you need each frame.

I don't know where your at with SDL, but it is essential that after each cycle, you have to use a function called SDL_Flip(Screen), this flips the page in SDL's video Buffer, and redraws the contents to the screen again.

Just at the end of your game loop you just use

SDL_Flip(Screen) ;

By the way, if I'm telling you stuff you already know, I'm not trying to be pretentious, I just don't know your experience level with SDL. :)

Re: Deleting surfaces in SDL

Posted: Wed Jan 14, 2009 2:33 pm
by Vortex
Well im fairly new to SDL ( i think im at tutorial 8 at lazyfoo´s ) and i use SDL_Flip() at the end im not sure why it dont work :roll:

Re: Deleting surfaces in SDL

Posted: Wed Jan 14, 2009 2:40 pm
by programmerinprogress
I used lazyfoo aswell, it was a very effective set of tutorials.

Could you explain to me, in bullet points, what your writing to the screen, how it is being drawn and refreshed aswell?

I would imagine it would be something like this.

-Start your loop, don't end loop till quit condition is met
- poll for events, control presence of menus and buttons etc
- FillRect an SDL_Rect the size of the screen to the screen (or a background texture, or several!)
- draw surfaces that ' got through' to the screen (such as menus, buttons, sprites etc)
-Flip the screen surface (SDL_Flip(Screen))
-any other caretaking you need to do to prevent a memory leak (although this probably wont be a problem unless your re-assigning surfaces(with new images) again and again)
-next iteration.

Re: Deleting surfaces in SDL

Posted: Wed Jan 14, 2009 2:55 pm
by MarauderIIC
Or just post all relevant sections of your code.

Re: Deleting surfaces in SDL

Posted: Wed Jan 14, 2009 3:08 pm
by Vortex
god damnit i wrote down the whole process of my main loop took me a while but then it didint get send and i have to rewrite.
if it is ok id rather post the loop, or sections of it.
ill write it down if you guys prefer that :cry:

Re: Deleting surfaces in SDL

Posted: Wed Jan 14, 2009 3:09 pm
by Vortex

Code: Select all

    while( quit == false )
    {
		SDL_Delay( 10 );
        //If there's events to handle
        	if( SDL_PollEvent( &event ) )
        {
            //Handle button events

			if(exitbutton.handle_events()==-1)
			{
				quit = true;
			}
			Uint8 *keystates = SDL_GetKeyState( NULL );

			//If a key was pressed
            if( event.type == SDL_KEYDOWN )
            {
				
                switch( event.key.keysym.sym )
                {
                    case SDLK_ESCAPE:
					{

						if( menu == true )
						{ menu = false; }
						else
						{
							menu = true;
						}
					}
                }
            }
            
            //If the user has Xed out the window
           if( event.type == SDL_QUIT )
            {
                //Quit the program
                quit = true;
            }
		}              
        //Show the button
		if ( menu == true )
		{
		if( ! buttonSheet )
		{
		exitbutton.boxPos(( SCREEN_WIDTH - 80 ) / 2, 120,80,60);
		buttonSheet = load_image( "button.png" );
        exitbutton.show();

		}
		}
		if ( menu == false )
		{
			if( buttonSheet )
			{
			exitbutton.boxPos(-100000,-10000,0,0);
			SDL_FreeSurface( buttonSheet );
			buttonSheet = NULL;
			}
		}
		
		showText("sometext",200,200);

        //Update the screen
        if( SDL_Flip( screen ) == -1 )
        {
            return 1;
        }
    }

Re: Deleting surfaces in SDL

Posted: Wed Jan 14, 2009 3:14 pm
by programmerinprogress
Got it!, if you notice, you're only asking it to show the button after you load the sheet, what you need to do is place the .Show() like this

Code: Select all

if ( menu == true )
      {
      if( ! buttonSheet )
      {
      exitbutton.boxPos(( SCREEN_WIDTH - 80 ) / 2, 120,80,60);
      buttonSheet = load_image( "button.png" );
      

      }
        exitbutton.show();
      }
you only need to load the image into the surface once, and set it's position once, but it is very important you draw it every frame.
Before you were just drawing it as you created it

Can I just suggest something (it's not essential) maybe you might want to think about pre-loading your surface into the memory, and then just not drawing it when you want to hide it, instead of freeing the surface and reloading it into the memory again, these functions can get a bit memory hungry...

Re: Deleting surfaces in SDL

Posted: Wed Jan 14, 2009 3:16 pm
by Vortex
Thanks dude it animates perfectly now, but it still dosent dissapear when i press escape again it just stop animate and is unclickable any idea on what might be wrong ?

Re: Deleting surfaces in SDL

Posted: Wed Jan 14, 2009 3:25 pm
by programmerinprogress
You need to draw something onto the screen to cover the old contents of the screen (like white washing a canvas)

to do this:

At the beginning of your code (somewhere before the while(Quit == false) loop) declare an SDL_Rect and initialise it to the size of the screen.
Then just fill it with black each time, i'll alter your code snippet to show you how that works

Code: Select all

 

SDL_Rect Backdrop = {0,0,SCREEN_WIDTH,SCREEN_HEIGHT}; // this is your rectangle, it's x position, y position, 
                                               //width (the screen width) and its height (screen height)
while( quit == false )
    {
      SDL_Delay( 10 );
        //If there's events to handle
           if( SDL_PollEvent( &event ) )
        {
            //Handle button events

         if(exitbutton.handle_events()==-1)
         {
            quit = true;
         }
         Uint8 *keystates = SDL_GetKeyState( NULL );

         //If a key was pressed
            if( event.type == SDL_KEYDOWN )
            {
            
                switch( event.key.keysym.sym )
                {
                    case SDLK_ESCAPE:
               {

                  if( menu == true )
                  { menu = false; }
                  else
                  {
                     menu = true;
                  }
               }
                }
            }
            
            //If the user has Xed out the window
           if( event.type == SDL_QUIT )
            {
                //Quit the program
                quit = true;
            }
      }  

        // draw clean backdrop 
       SDL_FillRect(Screen,Backdrop,SDL_MapRGB(Screen->format,255,255,255));   // this can be any colour you want , just 
                                                                             //change the numbers
        //Show the button
      if ( menu == true )
      {
      if( ! buttonSheet )
      {
      exitbutton.boxPos(( SCREEN_WIDTH - 80 ) / 2, 120,80,60);
      buttonSheet = load_image( "button.png" );
        exitbutton.show();

      }
      }
      if ( menu == false )
      {
         if( buttonSheet )
         {
         exitbutton.boxPos(-100000,-10000,0,0);
         SDL_FreeSurface( buttonSheet );
         buttonSheet = NULL;
         }
      }
      
      showText("sometext",200,200);

        //Update the screen
        if( SDL_Flip( screen ) == -1 )
        {
            return 1;
        }
    }

Re: Deleting surfaces in SDL

Posted: Wed Jan 14, 2009 3:31 pm
by Vortex
well it works now, the thing is that i want to show other stuff on the screen ( i will use this to make a really really basic game when i have read more tutorials ) so i cant have the screen all black, i guess i could make it the background color and just the size that the button takes but arent it any cleaner solution ?

Re: Deleting surfaces in SDL

Posted: Wed Jan 14, 2009 3:36 pm
by programmerinprogress
well, instead of drawing a black rectangle, you can alter the colour of the rectangle, or, even better, you can load and image that covers the screen and use that to 'white-wash' the screen.

To alter the colour of the rectangle go to this part in your code
SDL_FillRect(Screen,Backdrop,SDL_MapRGB(Screen->format,0,0,0));
and change the 3 0's to other values to get the desired colour
255,255,255 is white
(If you understand how the additive RGB system works inside your computer, I don't really need to go into any more detail)

The other solution (using an image as a backdrop) requires you to simply load the picture into a new surface (perhaps called Backdrop) , then you just apply that surface where I told the program to show the rectangle.

so instead of SDL_FillRect(Screen,Backdrop,SDL_MapRGB(Screen->format,0,0,0));
you can use your routine for applying surfaces instead, thus solving your problem! :)

EDIT: a great resource to find out the syntax and usage of SDL's functions is it's DocWiki page, which can be found here: http://sdl.beuc.net/sdl.wiki/FrontPage

I hope this helped!