Sign in to follow this  

SDL and key press events

This topic is 3842 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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;
}

Share this post


Link to post
Share on other sites
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)

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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]

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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 :)

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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]

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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).

Share this post


Link to post
Share on other sites
Quote:
Original post by Lazy Foo
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.


No problem, I was mostly wondering if it could be a case of not taking cross-platform issues in mind. [smile]

Share this post


Link to post
Share on other sites
Quote:
Original post by let_bound
No problem, I was mostly wondering if it could be a case of not taking cross-platform issues in mind. [smile]


Eh cut me some slack I'm learning :D Thanks again. All that headache over a bug that was documented and I didn't even think to look up something like that.

Share this post


Link to post
Share on other sites
Quote:
Original post by raeb
Quote:
Original post by let_bound
No problem, I was mostly wondering if it could be a case of not taking cross-platform issues in mind. [smile]


Eh cut me some slack I'm learning :D Thanks again. All that headache over a bug that was documented and I didn't even think to look up something like that.


That wasn't meant for you. [grin]

The bug isn't documented per se. That is, the bug isn't in SDL, but in one of the underlying libraries it happens to use (on X11 systems anyway). It should just teach you that checking return values is important. I understand it's often very cumbersome to do so while also learning an API. Just keep it on the back of your head. [smile]

Share this post


Link to post
Share on other sites

This topic is 3842 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this