Advertisement

SDL - Key presses

Started by November 16, 2011 03:26 AM
6 comments, last by AndersEkdahl 13 years, 3 months ago
[color="#333333"]So i've done some coding regarding showing what key is beeing pressed down at the moment. [color="#333333"]The code compiles and everything, but the screen is just black.
[color="#333333"]When I close down the application the image pops up for a split second, saying what key that was pressed down. It's like it's beeing saved to the very last moment in the buffer. What is going wrong?



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

const int screenWidth = 800;
const int screenHeight= 600;
SDL_Surface *displaySurface = NULL;
SDL_Surface *message = NULL;
SDL_Surface *background = NULL;
SDL_Surface *upMessage = NULL;
SDL_Surface *downMessage = NULL;
SDL_Surface *leftMessage = NULL;
SDL_Surface *rightMessage = NULL;

//The font that's going to be used
TTF_Font *font = NULL;

SDL_Event event;

//The color of the font
SDL_Color textColor = { 0, 0, 0 };

SDL_Surface* load_image(const std::string& filename);
bool pollInput(SDL_Event& event);
bool init();
void apply_surface( int x, int y, SDL_Surface* image, SDL_Surface* displaSurface, SDL_Rect* clip = NULL );
bool load_files();
void clean_up();


int main(int argc, char** argv)
{
bool quit = false;


//Initialize
if( init() == false )
{
return 1;
}

//Load the files
if( load_files() == false )
{
return 1;
}


//Generate the message surfaces
upMessage = TTF_RenderText_Solid( font, "Up was pressed.", textColor );
downMessage = TTF_RenderText_Solid( font, "Down was pressed.", textColor );
leftMessage = TTF_RenderText_Solid( font, "Left was pressed", textColor );
rightMessage = TTF_RenderText_Solid( font, "Right was pressed", textColor );

//Apply the images to the screen
apply_surface( 0, 0, background, displaySurface );




//The program will wait until the user either press 'x' or esc.
while(!quit)
{
quit = pollInput(event);
}
//If a message needs to be displayed
if( message != NULL )
{
//Apply the background to the screen
apply_surface( 0, 0, background, displaySurface );

//Apply the message centered on the screen
apply_surface( ( screenWidth - message->w ) / 2, ( screenHeight - message->h ) / 2, message, displaySurface );

//Null the surface pointer
message = NULL;
}

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


clean_up();
return 0;
}

bool init()
{
//If there is some problem initializing the graphics.
if(SDL_Init(SDL_INIT_VIDEO) < 0 )
{
SDL_Quit();
return 1;
}

//The surface
displaySurface = SDL_SetVideoMode( screenWidth, screenHeight, 32, SDL_SWSURFACE /*| SDL_FULLSCREEN*/ );
if(displaySurface == NULL)
{
SDL_Quit();
return 1;
}

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

//Set the window caption
SDL_WM_SetCaption( "Press arrowKey!", NULL );

//If everything initialized fine
return true;
}

bool load_files()
{
//Load the background image
background = load_image(".\\data\\background.bmp");

//If the background didn't load
if( background == NULL )
{
return false;
}

//Load the ball
font = TTF_OpenFont( ".\\data\\lazy.ttf", 72 );


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

return true;
}



void apply_surface( int x, int y, SDL_Surface* image, SDL_Surface* displaySurface, SDL_Rect* clip )
{
SDL_Rect rect;
rect.x = x;
rect.y = y;


//blit the images to surface
SDL_BlitSurface(image, clip, displaySurface, &rect);

}



bool pollInput(SDL_Event& event)
{
while(SDL_PollEvent(&event))
{

if(event.type == SDL_KEYDOWN)
{
//what key is pressed down? Then show the correct message or quit.
switch(event.key.keysym.sym)
{
case SDLK_UP: message = upMessage; break;
case SDLK_DOWN: message = downMessage; break;
case SDLK_LEFT: message = leftMessage; break;
case SDLK_RIGHT: message = rightMessage; break;
case SDL_QUIT: //If you want to quit using the 'x'
return true;
case SDLK_ESCAPE:
return true;

}
}
}

return false;
}


SDL_Surface* load_image(const std::string& filename) //load a image
{
SDL_Surface* surface = NULL;

SDL_Surface* newSurface = NULL;

surface = IMG_Load(filename.c_str());

if(surface != NULL) //if the file was loaded
{
newSurface = SDL_DisplayFormat(surface); // We create a new surface, to convert the 24BMP file to work faster on our 32bit
SDL_FreeSurface(surface); //
//
if(newSurface != NULL)
{
//Color key surface
SDL_SetColorKey( newSurface, SDL_SRCCOLORKEY, SDL_MapRGB( newSurface->format, 255,0,255 ) );

}
}

return newSurface;

}


void clean_up()
{
//Free the surfaces
SDL_FreeSurface( background );
SDL_FreeSurface( message );
SDL_FreeSurface( upMessage );
SDL_FreeSurface( downMessage );
SDL_FreeSurface( leftMessage );
SDL_FreeSurface( rightMessage );


//Close the font that was used
TTF_CloseFont( font );

//Quit SDL_ttf
TTF_Quit();

//Quit SDL
SDL_Quit();
}


[color="#333333"]So i've done some coding regarding showing what key is beeing pressed down at the moment. [color="#333333"]The code compiles and everything, but the screen is just black.
[color="#333333"]When I close down the application the image pops up for a split second, saying what key that was pressed down. It's like it's beeing saved to the very last moment in the buffer. What is going wrong?



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

const int screenWidth = 800;
const int screenHeight= 600;
SDL_Surface *displaySurface = NULL;
SDL_Surface *message = NULL;
SDL_Surface *background = NULL;
SDL_Surface *upMessage = NULL;
SDL_Surface *downMessage = NULL;
SDL_Surface *leftMessage = NULL;
SDL_Surface *rightMessage = NULL;

//The font that's going to be used
TTF_Font *font = NULL;

SDL_Event event;

//The color of the font
SDL_Color textColor = { 0, 0, 0 };

SDL_Surface* load_image(const std::string& filename);
bool pollInput(SDL_Event& event);
bool init();
void apply_surface( int x, int y, SDL_Surface* image, SDL_Surface* displaSurface, SDL_Rect* clip = NULL );
bool load_files();
void clean_up();


int main(int argc, char** argv)
{
bool quit = false;


//Initialize
if( init() == false )
{
return 1;
}

//Load the files
if( load_files() == false )
{
return 1;
}


//Generate the message surfaces
upMessage = TTF_RenderText_Solid( font, "Up was pressed.", textColor );
downMessage = TTF_RenderText_Solid( font, "Down was pressed.", textColor );
leftMessage = TTF_RenderText_Solid( font, "Left was pressed", textColor );
rightMessage = TTF_RenderText_Solid( font, "Right was pressed", textColor );

//Apply the images to the screen
apply_surface( 0, 0, background, displaySurface );




//The program will wait until the user either press 'x' or esc.
while(!quit)
{
quit = pollInput(event);
}
//If a message needs to be displayed
if( message != NULL )
{
//Apply the background to the screen
apply_surface( 0, 0, background, displaySurface );

//Apply the message centered on the screen
apply_surface( ( screenWidth - message->w ) / 2, ( screenHeight - message->h ) / 2, message, displaySurface );

//Null the surface pointer
message = NULL;
}

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


clean_up();
return 0;
}

bool init()
{
//If there is some problem initializing the graphics.
if(SDL_Init(SDL_INIT_VIDEO) < 0 )
{
SDL_Quit();
return 1;
}

//The surface
displaySurface = SDL_SetVideoMode( screenWidth, screenHeight, 32, SDL_SWSURFACE /*| SDL_FULLSCREEN*/ );
if(displaySurface == NULL)
{
SDL_Quit();
return 1;
}

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

//Set the window caption
SDL_WM_SetCaption( "Press arrowKey!", NULL );

//If everything initialized fine
return true;
}

bool load_files()
{
//Load the background image
background = load_image(".\\data\\background.bmp");

//If the background didn't load
if( background == NULL )
{
return false;
}

//Load the ball
font = TTF_OpenFont( ".\\data\\lazy.ttf", 72 );


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

return true;
}



void apply_surface( int x, int y, SDL_Surface* image, SDL_Surface* displaySurface, SDL_Rect* clip )
{
SDL_Rect rect;
rect.x = x;
rect.y = y;


//blit the images to surface
SDL_BlitSurface(image, clip, displaySurface, &rect);

}



bool pollInput(SDL_Event& event)
{
while(SDL_PollEvent(&event))
{

if(event.type == SDL_KEYDOWN)
{
//what key is pressed down? Then show the correct message or quit.
switch(event.key.keysym.sym)
{
case SDLK_UP: message = upMessage; break;
case SDLK_DOWN: message = downMessage; break;
case SDLK_LEFT: message = leftMessage; break;
case SDLK_RIGHT: message = rightMessage; break;
case SDL_QUIT: //If you want to quit using the 'x'
return true;
case SDLK_ESCAPE:
return true;

}
}
}

return false;
}


SDL_Surface* load_image(const std::string& filename) //load a image
{
SDL_Surface* surface = NULL;

SDL_Surface* newSurface = NULL;

surface = IMG_Load(filename.c_str());

if(surface != NULL) //if the file was loaded
{
newSurface = SDL_DisplayFormat(surface); // We create a new surface, to convert the 24BMP file to work faster on our 32bit
SDL_FreeSurface(surface); //
//
if(newSurface != NULL)
{
//Color key surface
SDL_SetColorKey( newSurface, SDL_SRCCOLORKEY, SDL_MapRGB( newSurface->format, 255,0,255 ) );

}
}

return newSurface;

}


void clean_up()
{
//Free the surfaces
SDL_FreeSurface( background );
SDL_FreeSurface( message );
SDL_FreeSurface( upMessage );
SDL_FreeSurface( downMessage );
SDL_FreeSurface( leftMessage );
SDL_FreeSurface( rightMessage );


//Close the font that was used
TTF_CloseFont( font );

//Quit SDL_ttf
TTF_Quit();

//Quit SDL
SDL_Quit();
}




It's because you only apply your message surface after quit is equal to zero, so right after you press escape or close the window, it exits the loop, displayed the message and quits

A quick fix to this would be to add an SDL_Delay(5000) rigt after your if statement after the loop
Doing this will allow you to press a key, the quit the program. You will then see the message for 5 sec
Advertisement

A quick fix to this would be to add an SDL_Delay(5000) rigt after your if statement after the loop
Doing this will allow you to press a key, the quit the program. You will then see the message for 5 sec



That would indeed be a quick fix, not my intention though. My intention were that the images would display when I press a key. If I press down it would show the message, and if I click another key it would show another message
You need to add your rendering inside of your while(!quit) loop. A more correct definition of what is happening is your while(!quit) loop is what your sitting there watching. Inside that loop you are doing nothing more then getting the input and setting your message variable. However inside that loop you are not attempting to draw the surface based on the message. So once your user hits x or escape you break from your main loop, THEN you check what the last message was and render that to the screen but it's to late your already closing your app. So basically put the if(message != null) block into your while(!quit) loop and you will start to see results.

Dan Mayor

Professional Programmer & Hobbyist Game Developer

Seeking team for indie development opportunities, see my classifieds post


You need to add your rendering inside of your while(!quit) loop. A more correct definition of what is happening is your while(!quit) loop is what your sitting there watching. Inside that loop you are doing nothing more then getting the input and setting your message variable. However inside that loop you are not attempting to draw the surface based on the message. So once your user hits x or escape you break from your main loop, THEN you check what the last message was and render that to the screen but it's to late your already closing your app. So basically put the if(message != null) block into your while(!quit) loop and you will start to see results.


It is true what you are saying! Stupid me for not seeing that. But yeah, I tried to put my if(message != null) to my while loop and it didn't help at all. It still waits for the input to quit. Am I doing something wrong or is it maybe something else that is wrong?



//The program will wait until the user either press 'x' or esc.
while(!quit)
{

//If a message needs to be displayed
if(message != NULL)
{
//Apply the background to the screen
apply_surface( 0, 0, background, displaySurface );

//Apply the message centered on the screen
apply_surface( ( screenWidth - message->w ) / 2, ( screenHeight - message->h ) / 2, message, displaySurface );

//Null the surface pointer
message = NULL;
}
quit = pollInput(event);


}
Done some more thinking, if I put my if(messages != NULL) to my while-loop. Does that mean that the if-statement will only execute if I press I key? That sounds.. Wrong.
Advertisement

Done some more thinking, if I put my if(messages != NULL) to my while-loop. Does that mean that the if-statement will only execute if I press I key? That sounds.. Wrong.
[/quote]
The body of the if statement will only execute during loop iterations where "message" is not null. The variable "message" is initially null, and is only given a value when the player presses a key. When the message has been drawn, you set "message" back to null.

It is all of these factors interacting that will cause the message to only be displayed the instant a key is pressed. Is that not what you intended?


Am I doing something wrong or is it maybe something else that is wrong?
[/quote]
You aren't flipping the screen. You have rendered the images to an off screen buffer, you need to flip it to really "apply" it to the screen. Move the call to SDL_Flip() inside your loop.

Your next problem will likely be that the image disappears too fast to make use of. One suggestion I have is to wait for keyup events before nulling out message, rather than nulling it immediately after it has been rendered.


Done some more thinking, if I put my if(messages != NULL) to my while-loop. Does that mean that the if-statement will only execute if I press I key? That sounds.. Wrong.

The body of the if statement will only execute during loop iterations where "message" is not null. The variable "message" is initially null, and is only given a value when the player presses a key. When the message has been drawn, you set "message" back to null.

It is all of these factors interacting that will cause the message to only be displayed the instant a key is pressed. Is that not what you intended?


Am I doing something wrong or is it maybe something else that is wrong?
[/quote]
You aren't flipping the screen. You have rendered the images to an off screen buffer, you need to flip it to really "apply" it to the screen. Move the call to SDL_Flip() inside your loop.

Your next problem will likely be that the image disappears too fast to make use of. One suggestion I have is to wait for keyup events before nulling out message, rather than nulling it immediately after it has been rendered.
[/quote]

Jeezus, glad I posted here! Thx for the fast reply, the flipping was the problem. Cheers :)

This topic is closed to new replies.

Advertisement