SOLVED: SDL screen doesn't stay up

Started by
8 comments, last by osirius 17 years, 10 months ago
I've been going through the SDL tutorials at http://lazyfooproductions.com/SDL_tutorials/index.php , however after finishing Lesson 13 I decided to redo some of the code in the tutorials in a way that makes more sense to me. The problem is that after the line 'SDL_Flip( m_screen );' I have 'SDL_Delay( 2000 );' so that the screen stays up for 2 seconds, however after compiling and running the program the screen doesn't stay up, it just pops up very fast and then disappears. I can't figure out why. Here's the code (the bits that are commented out are the way I wrote the code the first time, I then commented those bits out and replaced them in an attempt to get the screen to stay up, but it didn't work):

#include "SDL/SDL.h"
#include "SDL/SDL_image.h"
#include "SDL/SDL_ttf.h"
#include <string>

class Screen
{
public:
	Screen::Screen( int width,
			int height,
			int bpp ): m_width( width ),
				   m_height( height ),
				   m_bpp( bpp )
	{
		init();
	}

	bool init();
	void quit();

	void set_font( TTF_Font* font );
	void set_text_color( SDL_Color textColor );

	void surface_to_screen( int x,
				int y,
				SDL_Surface* surface,
				SDL_Rect* clip = NULL );

	void text_to_screen( int x, 
			     int y,
			     std::string textString );

	void surface_to_surface( int x,
				 int y,
				 SDL_Surface* source,
				 SDL_Surface* destination,
				 SDL_Rect* clip = NULL );

	void text_to_surface( int x,
			      int y,
			      std::string textString,
			      SDL_Surface* surface );

	bool update_screen();
private:
	int m_width;
	int m_height;
	int m_bpp;

	SDL_Surface* m_screen;
	TTF_Font* m_font;
	SDL_Color m_textColor;
};

bool Screen::init()
{
	if( SDL_Init( SDL_INIT_EVERYTHING ) == -1 )
	{
		return false;
	}

	m_screen = SDL_SetVideoMode( m_width, m_height, m_bpp, SDL_SWSURFACE );

	if( m_screen == NULL )
	{
		return false;
	}

	if( TTF_Init() == -1 )
	{
		return false;
	}

	m_font = TTF_OpenFont( "lazy.ttf", 28 );

	if( m_font == NULL )
	{
		return false;
	}

	SDL_Color color = { 255, 255, 255 };
	m_textColor = color;

	return true;
}

void Screen::quit()
{
	SDL_FreeSurface( m_screen );
	TTF_CloseFont( m_font );
	TTF_Quit();
	SDL_Quit();
}

void Screen::set_font( TTF_Font* font )
{
	m_font = font;
}

void Screen::set_text_color( SDL_Color textColor )
{
	m_textColor = textColor;
}

void Screen::surface_to_screen( int x,
				int y,
				SDL_Surface* surface,
				SDL_Rect* clip )
{
	SDL_Rect offset;
	offset.x = x;
	offset.y = y;

	SDL_BlitSurface( surface, clip, m_screen, &offset );
}

void Screen::text_to_screen( int x, 
			     int y,
			     std::string textString )
{
	SDL_Surface* text = TTF_RenderText_Solid( m_font, textString.c_str(), m_textColor );
	surface_to_screen( x, y, text );
}

void Screen::surface_to_surface( int x,
				 int y,
				 SDL_Surface* source,
				 SDL_Surface* destination,
				 SDL_Rect* clip )
{
	SDL_Rect offset;
	offset.x = x;
	offset.y = y;

	SDL_BlitSurface( source, clip, destination, &offset );
}

void Screen::text_to_surface( int x,
			      int y,
			      std::string textString,
			      SDL_Surface* surface )
{
	SDL_Surface* text = TTF_RenderText_Solid( m_font, textString.c_str(), m_textColor );
	surface_to_surface( x, y, text, surface );
}

bool Screen::update_screen()
{
	//if( SDL_Flip( m_screen ) == -1 )
	//{
	//	return false;
	//}

	SDL_Flip( m_screen );

	SDL_Delay( 2000 );

	return true;
}

int main()
{
	Screen testScreen( 640, 480, 32 );

	if( testScreen.init() == false )
	{
		return 1;
	}

	testScreen.text_to_screen( 0, 0, "blah" );

	//if( testScreen.update_screen() == false )
	//{
	//	return 1;
	//}

	testScreen.update_screen();

	SDL_Delay( 2000 );

	testScreen.quit();

	return 0;
}



[Edited by - osirius on July 5, 2006 1:57:22 PM]
-----Build a man a fire, and he will be warm for the night. Set a man on fire and he'll be warm for the rest of his life.
Advertisement
Your Screen constructor calls init. Then, you try to call init again in main.
Quote:Original post by Dave Hunt
Your Screen constructor calls init. Then, you try to call init again in main.


and your quit should not release m_screen because you do not own this and sdl will clean it up.
Quote:Original post by Dave Hunt
Your Screen constructor calls init. Then, you try to call init again in main.


Ah yes, thanks for that. However after commenting out the part that calls testScreen.init() in main(), recompiling and running the program, I now get "Fatal signal: Segmentation Fault (SDL Parachute Deployed)". :-(
-----Build a man a fire, and he will be warm for the night. Set a man on fire and he'll be warm for the rest of his life.
Quote:Original post by Anonymous Poster
Quote:Original post by Dave Hunt
Your Screen constructor calls init. Then, you try to call init again in main.


and your quit should not release m_screen because you do not own this and sdl will clean it up.


Thanks, that's also true. I've commented out that part but the code still gives Parachute Deployed when run.
-----Build a man a fire, and he will be warm for the night. Set a man on fire and he'll be warm for the rest of his life.
Quote:...commenting out the part that calls testScreen.init() in main()...


Is that wise?
Your init returns a bool which is for success or failure, calling it in the constructor can be done but then you would throw an exception otherwise how else would you know if it was successful?

You should have removed the init() call from your constructor. Otherwise, you have no way of checking the return value and handling the error gracefully. As it is, if init() fails, you won't know about it, and the program will continue trying to execute with uninitialized stuff.
Sorry, you're right, I should run init() in main(), not in the class constructor. To avoid confusion here's the code again with the corrections you've all suggested (the code no longer gives Parachute Deployed, however the screen pops up very quickly again and then disappears):

// sdl_screen_class.cpp#include "SDL/SDL.h"#include "SDL/SDL_image.h"#include "SDL/SDL_ttf.h"#include <string>class Screen{public:	Screen::Screen( int width,			int height,			int bpp ): m_width( width ),				   m_height( height ),				   m_bpp( bpp )	{}	bool init();	void quit();	void set_font( TTF_Font* font );	void set_text_color( SDL_Color textColor );	void surface_to_screen( int x,				int y,				SDL_Surface* surface,				SDL_Rect* clip = NULL );	void text_to_screen( int x, 			     int y,			     std::string textString );	void surface_to_surface( int x,				 int y,				 SDL_Surface* source,				 SDL_Surface* destination,				 SDL_Rect* clip = NULL );	void text_to_surface( int x,			      int y,			      std::string textString,			      SDL_Surface* surface );	bool update_screen();private:	int m_width;	int m_height;	int m_bpp;	SDL_Surface* m_screen;	TTF_Font* m_font;	SDL_Color m_textColor;};bool Screen::init(){	if( SDL_Init( SDL_INIT_EVERYTHING ) == -1 )	{		return false;	}	m_screen = SDL_SetVideoMode( m_width, m_height, m_bpp, SDL_SWSURFACE );	if( m_screen == NULL )	{		return false;	}	if( TTF_Init() == -1 )	{		return false;	}	m_font = TTF_OpenFont( "lazy.ttf", 28 );	if( m_font == NULL )	{		return false;	}	SDL_Color color = { 255, 255, 255 };	m_textColor = color;	return true;}void Screen::quit(){	//SDL_FreeSurface( m_screen );	TTF_CloseFont( m_font );	TTF_Quit();	SDL_Quit();}void Screen::set_font( TTF_Font* font ){	m_font = font;}void Screen::set_text_color( SDL_Color textColor ){	m_textColor = textColor;}void Screen::surface_to_screen( int x,				int y,				SDL_Surface* surface,				SDL_Rect* clip ){	SDL_Rect offset;	offset.x = x;	offset.y = y;	SDL_BlitSurface( surface, clip, m_screen, &offset );}void Screen::text_to_screen( int x, 			     int y,			     std::string textString ){	SDL_Surface* text = TTF_RenderText_Solid( m_font, textString.c_str(), m_textColor );	surface_to_screen( x, y, text );}void Screen::surface_to_surface( int x,				 int y,				 SDL_Surface* source,				 SDL_Surface* destination,				 SDL_Rect* clip ){	SDL_Rect offset;	offset.x = x;	offset.y = y;	SDL_BlitSurface( source, clip, destination, &offset );}void Screen::text_to_surface( int x,			      int y,			      std::string textString,			      SDL_Surface* surface ){	SDL_Surface* text = TTF_RenderText_Solid( m_font, textString.c_str(), m_textColor );	surface_to_surface( x, y, text, surface );}bool Screen::update_screen(){	//if( SDL_Flip( m_screen ) == -1 )	//{	//	return false;	//}	SDL_Flip( m_screen );	SDL_Delay( 2000 );	return true;}int main(){	Screen testScreen( 640, 480, 32 );	if( testScreen.init() == false )	{		return 1;	}	testScreen.text_to_screen( 0, 0, "blah" );	//if( testScreen.update_screen() == false )	//{	//	return 1;	//}	testScreen.update_screen();	SDL_Delay( 2000 );	testScreen.quit();	return 0;}
-----Build a man a fire, and he will be warm for the night. Set a man on fire and he'll be warm for the rest of his life.
How about outputting some messages when things fail? Right now, if init() fails, all it does is exit. Chances are that's where your problem is. Output a message at each exit point and you'll know which one it was and why.
Quote:Original post by Dave Hunt
How about outputting some messages when things fail? Right now, if init() fails, all it does is exit. Chances are that's where your problem is. Output a message at each exit point and you'll know which one it was and why.


Aha! Thanks. After doing that I found that 'm_font == NULL' and 'testScreen.init() == false' where both evaluated as true - the problem was I forgot to put the font file lazy.ttf in the same directory I was compiling the code in. Dumb mistake :-( .

While I'm at it, if you have any general comments about the way I organized my code and how I could improve it, that'd be useful (I'm still just a beginner).
-----Build a man a fire, and he will be warm for the night. Set a man on fire and he'll be warm for the rest of his life.

This topic is closed to new replies.

Advertisement