SDL and key press events

Started by
11 comments, last by let_bound 16 years, 10 months ago
So I'm working my way through the SDL tutorials written by lazy foo productions as suggested by the faq. I'm on the 8th lesson and I'm not quite sure why but the window loads fine, however nothing happens when I actually press an arrow key. When it's run, it doesn't respond at all (doesn't seem to even make it to the switch statement?). Downloading lazy foo's original code behaves in the same way. Any help? I compile it by: g++ -o lesson8 main.cpp -lSDL -lSDL_image -lSDL_ttf Here's my version of the source code:

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

// screen attributes
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
const int SCREEN_BPP =32;

// surfaces
SDL_Surface *background = NULL;
SDL_Surface *screen = NULL;

SDL_Surface *message = NULL;
SDL_Surface *up = NULL;
SDL_Surface *down = NULL;
SDL_Surface *left = NULL;
SDL_Surface *right = NULL;

// event handler
SDL_Event event;

// the fonts & font color
TTF_Font *font = NULL;
SDL_Color textColor = {255, 255, 255};

// func decs
bool loadFiles();
bool init();
void clean_up();
SDL_Surface *loadImage(std::string);
void applySurface( int, int, SDL_Surface*, SDL_Surface*, SDL_Rect*);

bool init()
{
	// init SDL
	if (SDL_Init( SDL_INIT_EVERYTHING) == -1)
		return false;
	
	screen = SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT,
							SCREEN_BPP, SDL_SWSURFACE);
	
	if (screen == NULL)
		return false;
	
	// init ttf
	if (TTF_Init() == -1)
		return false;
	
	SDL_WM_SetCaption( "Keypress Testing", NULL);
	
	return true;
}

bool loadFiles()
{
	background = loadImage( "background.png" );
	font = TTF_OpenFont( "lazy.ttf", 72 );
	
	if (background == NULL)
		return false;
	
	if (font == NULL)
		return false;
	
	// Everything loaded fine
	return true;
}

// Free's the surfaces, fonts, and exits SDL
void clean_up()
{
	SDL_FreeSurface( background );
	SDL_FreeSurface( message );
	SDL_FreeSurface( up );
	SDL_FreeSurface( down );
	SDL_FreeSurface( left );
	SDL_FreeSurface( right );
	TTF_CloseFont( font );
	TTF_Quit();
	SDL_Quit();
}

// load a image into memory as a surface
SDL_Surface *loadImage(std::string filename)
{
	// temp image
	SDL_Surface* loadedImage = NULL;
	
	// optimized image
	SDL_Surface* optimizedImage = NULL;
	
	// load the image
	loadedImage = IMG_Load( filename.c_str() );
	if (loadedImage != NULL)
	{
		// optimize image and free old image
		optimizedImage = SDL_DisplayFormat( loadedImage );
		SDL_FreeSurface( loadedImage );
		
		if (optimizedImage != NULL)
		{ // Color key the surface
			SDL_SetColorKey( optimizedImage, SDL_RLEACCEL | SDL_SRCCOLORKEY,
						SDL_MapRGB( optimizedImage->format, 0, 0xFF, 0xFF ) );
		}
	}
	return optimizedImage;
}

// Blit a surface from source to the destination at x,y
void applySurface( int x, int y, SDL_Surface* source, 
						  SDL_Surface* destination,
						  SDL_Rect* clip = NULL)
{
	// temp rec to hold offsets
	SDL_Rect offset;
	
	offset.x = x;
	offset.y = y;
	SDL_BlitSurface(source, clip, destination, &offset);
}

int main( int argc, char* args[] )
{
	bool quit = false;
	
	// Initialize SDL and load the files
	if ( init() == false )
		return 1;
	if ( loadFiles() == false )
		return 1;
	
	// Create the messages
	up = TTF_RenderText_Solid(font, "Up was pressed", textColor);
	down = TTF_RenderText_Solid(font, "Down was pressed", textColor);
	left = TTF_RenderText_Solid(font, "Left was pressed", textColor);
	right = TTF_RenderText_Solid(font, "Right was pressed", textColor);

	applySurface(0, 0, background, screen);
	
	while (!quit)
	{
		if ( SDL_PollEvent( &event ) )
		{
			if( event.type == SDL_KEYDOWN )
			{
				// set the text
				switch( event.key.keysym.sym )
				{
					case SDLK_UP: message = up; break;
					case SDLK_DOWN: message = down; break;
					case SDLK_LEFT: message = left; break;
					case SDLK_RIGHT: message = right; break;
				}
			}
			else if( event.type == SDL_QUIT )
				quit = true;
			
		}
		// Message to the screen
		if ( message != NULL )
		{
			applySurface(0, 0, background, screen);
			applySurface( (SCREEN_WIDTH - message->w) / 2,
						(SCREEN_HEIGHT - message->h) / 2,
						message, screen );
		
			message = NULL;
		}
		// Update the screen
		if ( SDL_Flip( screen ) == -1 )
			return 1;
	}
	// Clean and exit
	clean_up();
	return 0;
}
Advertisement
I'm not awake enough to look at it in depth but just real quick what is keeping it from clearing the message instantly? At first glance it looks like a message is displayed only when message != NULL. But then message is instantly set back to NULL which would happen way to fast to really see.

SDL only tracks Changes so if you press the key it will only set the message ONE time then get reset by the desplay function. So you cant hold the key down but would have to press it reeeeeeeeeeeeeally fast to see anything.

I'm thinking you shouldn't reset the message var until you get SDL_KEYUP or RELEASED(whichever it is)
------------------------------------------------------------- neglected projects Lore and The KeepersRandom artwork
Goober King seems to be correct. You should keep that message != NULL for a longer time to see anything, or you'll end up with a single frame and, since your program is very simple, your framerate may be high enough for you to see anything on a single frame alone.

I second his advice on keeping that message until you get a SDL_KEYUP event.
Well I took your advice but the problem seems to be that the message isn't being set to whatever key is pressed, it just stays null. I did make the changes to wait for a keyup event to make message = null. Out of curiousity I tried putting one of the messages on the screen as soon as main gets going. When I run it with:

applySurface( (SCREEN_WIDTH - up->w) / 2,(SCREEN_HEIGHT - up->h) / 2,up, screen );

I get a segmentation fault, so I'm still confused. What would cause it to do that? Here's the new main method:

int main( int argc, char* args[] ){	bool quit = false;		// Initialize SDL and load the files	if ( init() == false )		return 1;	if ( loadFiles() == false )		return 1;		// Create the messages	up = TTF_RenderText_Solid(font, "Up was pressed", textColor);	down = TTF_RenderText_Solid(font, "Down was pressed", textColor);	left = TTF_RenderText_Solid(font, "Left was pressed", textColor);	right = TTF_RenderText_Solid(font, "Right was pressed", textColor);	// Put the background on so it isn't just black.	applySurface(0, 0, background, screen);        // This next line causes segmentation fault	//applySurface( (SCREEN_WIDTH - up->w) / 2,	//					(SCREEN_HEIGHT - up->h) / 2,	//					up, screen );		while (!quit)	{		if ( SDL_PollEvent( &event ) )		{			if( event.type == SDL_KEYDOWN )			{				switch( event.key.keysym.sym )				{					case SDLK_UP: message = up; break;					case SDLK_DOWN: message = down; break;					case SDLK_LEFT: message = left; break;					case SDLK_RIGHT: message = right; break;				}			}						else if( event.type == SDL_KEYUP )				message = NULL;							else if( event.type == SDL_QUIT )				quit = true;		}				// Draw the screen		if ( message != NULL )		{			applySurface(0, 0, background, screen);			applySurface( (SCREEN_WIDTH - message->w) / 2,						(SCREEN_HEIGHT - message->h) / 2,						message, screen );		}		if ( SDL_Flip( screen ) == -1 )			return 1;	}	// Clean and exit	clean_up();	return 0;}


*********************** EDIT *************************

So I tried this all out on my spare WinXP partition using VC++ and it worked like a charm, so the code isn't at fault from what I can tell. Thanks for the help on that other problem I thought I had.

[Edited by - raeb on June 6, 2007 2:48:47 PM]
Quote:Original post by raeb
Well I took your advice but the problem seems to be that the message isn't being set to whatever key is pressed, it just stays null. I did make the changes to wait for a keyup event to make message = null. Out of curiousity I tried putting one of the messages on the screen as soon as main gets going. When I run it with:

applySurface( (SCREEN_WIDTH - up->w) / 2,(SCREEN_HEIGHT - up->h) / 2,up, screen );

I get a segmentation fault, so I'm still confused. What would cause it to do that? Here's the new main method:

*** Source Snippet Removed ***

*********************** EDIT *************************

So I tried this all out on my spare WinXP partition using VC++ and it worked like a charm, so the code isn't at fault from what I can tell. Thanks for the help on that other problem I thought I had.


Just because it works under one circumstance doen't mean the code is right. It is kinda fishy. What were you building under before?

**edit
BTW were you using SDL_Delay(X) function anyware to keep the message up without checking for the key up event? The lazy foo snippit I'm looking at does. If you plan on using SDL as input you need to know about that gotcha. They even talk about it in the Doc files which are really easy to use btw.
------------------------------------------------------------- neglected projects Lore and The KeepersRandom artwork
Works under WinXP using Visual Studio 2k5 standard ed.
It doesn't work using ubuntu (fiesty fawn). I have the libsdl-devel packages installed for the extentions. I'm compiling with g++ -o lesson main.cpp -lSDL -lSDL_image -lSDL_ttf. I'm not seeing any sdl delay function at the tutorials I'm following: http://lazyfoo.net/SDL_tutorials/lesson08/index.php What docs are you looking at as well? (for my reference, I'd appreciate it :)
Quote:Original post by raeb
Works under WinXP using Visual Studio 2k5 standard ed.
It doesn't work using ubuntu (fiesty fawn). I have the libsdl-devel packages installed for the extentions. I'm compiling with g++ -o lesson main.cpp -lSDL -lSDL_image -lSDL_ttf. I'm not seeing any sdl delay function at the tutorials I'm following: http://lazyfoo.net/SDL_tutorials/lesson08/index.php What docs are you looking at as well? (for my reference, I'd appreciate it :)


I think it was this one.

Quote:
//Wait 2 seconds SDL_Delay( 2000 );
We call SDL_Delay() so that the window doesn't just flash on the screen for a split second. SDL_Delay() accepts time in milliseconds, or 1/1000 of a second.

So the window will stay up for 2000/1000 of a second or 2 seconds.


It's near the end. As you can see it mentions the issue.

One think you may want to try is using Dev-Cpp which uses the windows version of gcc. Which makes a lot of sence if you are going to cross compile. I use it and have an OpenGL/SDL game that compiles under windows and linux with zero code changes. Anyway, not all compilers are created equal and not all enforce the standards in the same way or to the same extent.
------------------------------------------------------------- neglected projects Lore and The KeepersRandom artwork
You aren't checking the value returned by SDL_RenderText_Solid()[1]. I'm willing to bet it's the cause of all your problem, because you're attempting to render whitespaces, and that will trigger a bug in Freetype[2]. Replacing it with SDL_RenderText_Blended() will do the trick, but it'll be blended, not solid.

Is LazyFoo testing his tutorials on non-Microsoft systems at all? I'm asking because this is a common bug on recent X11 systems, and because of the unportable way the SDL header files are included. This isn't a criticism of his tutorials, BTW, just an honest question.

Hope this helps.


1. Just doing so and printing the output of SDL_GetError() in case of failure lead to this error message: "Failed loading DPMSDisable: /usr/lib/libX11.so.6: undefined symbol: DPMSDisable".
2. http://lists.libsdl.org/pipermail/sdl-libsdl.org/2007-March/060463.html


EDIT: typo


[Edited by - let_bound on June 6, 2007 10:42:46 PM]
Quote:Original post by let_bound
Is LazyFoo testing his tutorials on non-Microsoft systems at all? I'm asking because this is a common bug on recent X11 systems.


It worked on my SuSE 9.3. I need to install a newer distro.

I do mention trying to use alternative rendering in the tutorial, though.

Learn to make games with my SDL 2 Tutorials

Quote:Original post by let_bound
You aren't checking the value returned by SDL_RenderText_Solid()[1]. I'm willing to bet it's the cause of all your problem, because you're attempting to render whitespaces, and that will trigger a bug in Freetype[2]. Replacing it with SDL_RenderText_Blended() will do the trick, but it'll be blended, not solid.

Is LazyFoo testing his tutorials on non-Microsoft systems at all? I'm asking because this is a common bug on recent X11 systems, and because of the unportable way the SDL header files are included. This isn't a criticism of his tutorials, BTW, just an honest question.

Hope this helps.


1. Just doing so and printing the output of SDL_GetError() in case of failure lead to this error message: "Failed loading DPMSDisable: /usr/lib/libX11.so.6: undefined symbol: DPMSDisable"
.
2. http://lists.libsdl.org/pipermail/sdl-libsdl.org/2007-March/060463.html


EDIT: typo

Wow, that fixed it 100%. Thanks for the links (especially to the different functions and what they do).

This topic is closed to new replies.

Advertisement