Sign in to follow this  

SDL_key

This topic is 2856 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

Hi! My first post here. I have a problem with toggling sound on and off (game pause aswell). This is a part of the game loop, the only part that i can't get to work. Game checks if the 's' button is pressed and then, if snd is true, sets it to false (sound is on, make it off) and tells surface msgsnd to tell it's now off, and the other way around. Now i know, that it just runs them both at the same time, so it's ending with sound on all the time, but how can i make it that when i press it once it turns it on, when i press it again, it turns off. Atm the sound is just a bool, nothing more. The same goes with the pause game. Rightnow i've got to use 'up' for entering and 'down' for exitting pause. I can't use 'space' for both. I would appreciate any kind of help, here's the part of code:
Quote:
while( SDL_PollEvent( &event ) ) { if( event.type == SDL_KEYDOWN) { if( event.key.keysym.sym == SDLK_s ) { if (snd == true) { snd = false; msgsnd = TTF_RenderText_Solid( font2, "SOUND: OFF", textColor ); } if (snd == false) { snd = true; msgsnd = TTF_RenderText_Solid( font2, "SOUND: ON", textColor ); } } } }

Share this post


Link to post
Share on other sites
You could fix this by changing:
if (snd == false)
to:
else if (snd == false)
Check this out.

However, a better solution would be something like:


if( event.key.keysym.sym == SDLK_s )
{
snd = !snd; // toggle snd
msgsnd = TTF_RenderText_Solid( font2, snd ? "SOUND: ON" : "SOUND: OFF", textColor ); // is this really the best place to render this string?
}

Share this post


Link to post
Share on other sites

if (snd == true)
{
snd = false;
msgsnd = TTF_RenderText_Solid( font2, "SOUND: OFF", textColor );
}
if(snd == false)
{
snd = true;
msgsnd = TTF_RenderText_Solid( font2, "SOUND: ON", textColor );
}

Your code is equivalent to:

if (snd == true)
{
msgsnd = TTF_RenderText_Solid( font2, "SOUND: OFF", textColor );
}

snd = true;
msgsnd = TTF_RenderText_Solid( font2, "SOUND: ON", textColor );

Try using if...else... to express such conditions. Also, you should probably be de-allocating the original msgsnd surface, or else you will leak memory.

SDL_FreeSurface(soundMessage);
if(sound)
{
sound = false;
soundMessage = TTF_RenderText_Solid( font2, "SOUND: OFF", textColor );
}
else
{
sound = true;
soundMessage = TTF_RenderText_Solid( font2, "SOUND: ON", textColor );
}


Note that you should avoid compressing your variable names, it makes your code harder to read.

Share this post


Link to post
Share on other sites
With this code:
if (snd == true)
{
snd = false;
msgsnd = TTF_RenderText_Solid( font2, "SOUND: OFF", textColor );
}
if (snd == false)
{
snd = true;
msgsnd = TTF_RenderText_Solid( font2, "SOUND: ON", textColor );
}
If snd is true, it will be set to false, but then of course the next block of code will be executed immediately and it'll be set back to true, which isn't what you want. You can fix the problem by using an if-else statement (rather than two consecutive 'if' statements). You could also toggle the 'snd' variable like this:
snd = !snd;
And then set the message text as appropriate depending on the new value of 'snd'.

[Too slow...]

Share this post


Link to post
Share on other sites
Thanks for all the replies, i just added 'else'. Didnt seem to think of it myself.
Quote:
Also, you should probably be de-allocating the original msgsnd surface, or else you will leak memory.

What do you mean by that?

Share this post


Link to post
Share on other sites
Every time you call TTF_RenderText_*(), memory is allocated. If you don't free it, your program will consume more and more memory over time. This will cause it to slow down or crash if it is a long running process (imagine a game server running 24/7). This is why I included a call to "SDL_FreeSurface()" in my example.

Share this post


Link to post
Share on other sites
I am too slow typing. I just had to delete my whole post since it's already been said....

One important thing to note: if SDL_EnableKeyRepeat is enabled, then you will have repeating key down events, thus toggling snd back and forth while the key is pressed.

And the other nit-pick is:

if ( snd )
{
...
}

if ( !snd )
{
...
}



is easier to read than:

if ( snd == true )
{
...
}

if ( snd == false )
{
...
}

Share this post


Link to post
Share on other sites
This is what i'm making - http://yy.lv/upload/index.php?ACT=4&f=108708&ext=RAR
SPACE - pause
Mouse controls player 1
1 - beginner AI
2 - expert AI
r - reset
s - sound

When the game is in pause mode (basically it's a 'while(...)' loop) sound button works nicely, but when it's in the main loop it act's like it's held down.
And i can't get out of pause mode by tapping space again.
Everything else seems to work nicely.

Share this post


Link to post
Share on other sites
We'll need to see some code to be able to diagnose that. Could you post the event handling code in question?

Use [source]..[/source] tags to keep it tidy.

Share this post


Link to post
Share on other sites
I'm latvian, so some ofthe variables are in latvian aswell.
This is the main loop:

int loop()
{
while(!quit)
{
while( SDL_PollEvent( &event ) )
{

}
SDL_Delay(1);
if( event.type == SDL_KEYDOWN )
{
if( event.key.keysym.sym == SDLK_s )
{
if (snd)
{
snd = false;
msgsnd = TTF_RenderText_Solid( font2, "SOUND: OFF", textColor );
}
else if (!snd)
{
snd = true;
msgsnd = TTF_RenderText_Solid( font2, "SOUND: ON", textColor );
}
}
}
if (sp2lvl == 1)
{
vsp2 = 0.30;
msglvl = TTF_RenderText_Solid( font2, "BEGINNER", textColor );
}
if (sp2lvl == 2)
{
vsp2 = 0.40;
msglvl = TTF_RenderText_Solid( font2, "EXPERT", textColor );
}
if (snd)
{
msgsnd = TTF_RenderText_Solid( font2, "SOUND: ON", textColor );
}
if (!snd)
{
msgsnd = TTF_RenderText_Solid( font2, "SOUND: OFF", textColor );
}
ball_fizika();
Speletaji_fizika();
Punkti();
Speletaji();
SDL_FillRect(screen , NULL , 0x38A2CF);
apply_surface( 318, 0, middle, screen );
apply_surface( 0, 0, side1, screen );
apply_surface( 0, 394, side2, screen );
apply_surface( xball, yball, ball, screen );
apply_surface( xsp1, ysp1, SP1, screen );
apply_surface( xsp2, ysp2, SP2, screen );
if (Points1 <= 9)
{
apply_surface( SCREEN_WIDTH/2-19, 2, msgPoints1, screen );
}
if (Points1 > 9)
{
apply_surface( SCREEN_WIDTH/2-28, 2, msgPoints1, screen );
}
if (Points1 > 99)
{
apply_surface( SCREEN_WIDTH/2-53, 2, msgPoints1, screen );
}
if (Points2 <= 9)
{
apply_surface( SCREEN_WIDTH/2+5, 2, msgPoints2, screen );
}
if (Points2 > 9)
{
apply_surface( SCREEN_WIDTH/2+5, 2, msgPoints2, screen );
}
apply_surface( 2, 3, msglvl, screen );
apply_surface( 2, 13, msgsnd, screen );
apply_surface( 0, SCREEN_HEIGHT-20, msgcredits, screen );

if( event.type == SDL_KEYDOWN )
{
switch( event.key.keysym.sym )
{
case SDLK_SPACE: pauze(); bpauze = true; break;
case SDLK_q: quit = true; break;
case SDLK_ESCAPE: quit = true; break;
case SDLK_2: sp2lvl = 2; break;
case SDLK_1: sp2lvl = 1; break;
case SDLK_r: greset(); reset = true; break;
}
}

if( SDL_Flip( screen ) == -1 )
{
return 1;
}
if( event.type == SDL_QUIT )
{
quit = true;
}
}
}

This is pause loop:

void pauze()
{
while( bpauze == true )
{
msgPauze = TTF_RenderText_Solid( font, "PAUSE", textColor );
msginstr4 = TTF_RenderText_Solid( font2, "S: SOUND", textColor );
msginstr3 = TTF_RenderText_Solid( font2, "R: RESET", textColor );
msginstr2 = TTF_RenderText_Solid( font2, "2: EXPERT", textColor );
msginstr1 = TTF_RenderText_Solid( font2, "1: BEGINNER", textColor );
SDL_FillRect(screen , NULL , 0x38A2CF);
apply_surface( SCREEN_WIDTH/2+4, SCREEN_HEIGHT/2, msgPauze, screen );
apply_surface( SCREEN_WIDTH/2+4, SCREEN_HEIGHT/2-9, msginstr1, screen );
apply_surface( SCREEN_WIDTH/2+4, SCREEN_HEIGHT/2-8-12, msginstr2, screen );
apply_surface( SCREEN_WIDTH/2+4, SCREEN_HEIGHT/2-8-10-13, msginstr3, screen );
apply_surface( SCREEN_WIDTH/2+4, SCREEN_HEIGHT/2-8-10-10-14, msginstr4, screen );
apply_surface( 2, 3, msglvl, screen );
apply_surface( 318, 0, middle, screen );
apply_surface( 0, 0, side1, screen );
apply_surface( 0, 394, side2, screen );
apply_surface( xball, yball, ball, screen );
apply_surface( xsp1, ysp1, SP1, screen );
apply_surface( xsp2, ysp2, SP2, screen );
apply_surface( 2, 13, msgsnd, screen );
apply_surface( 0, SCREEN_HEIGHT-20, msgcredits, screen );
if (Points1 <= 9)
{
apply_surface( SCREEN_WIDTH/2-19, 2, msgPoints1, screen );
}
if (Points1 > 9)
{
apply_surface( SCREEN_WIDTH/2-28, 2, msgPoints1, screen );
}
if (Points1 > 99)
{
apply_surface( SCREEN_WIDTH/2-53, 2, msgPoints1, screen );
}
if (Points2 <= 9)
{
apply_surface( SCREEN_WIDTH/2+5, 2, msgPoints2, screen );
}
if (Points2 > 9)
{
apply_surface( SCREEN_WIDTH/2+5, 2, msgPoints2, screen );
}

SDL_Flip( screen );
while( SDL_PollEvent( &event ) )
{

if( event.type == SDL_KEYDOWN)
{
if( event.key.keysym.sym == SDLK_SPACE )
{
bpauze = false;
break;
}
if( event.key.keysym.sym == SDLK_r )
{
bpauze = false;
reset = true;
greset();
}
if( event.key.keysym.sym == SDLK_s )
{
if (snd)
{
snd = false;
msgsnd = TTF_RenderText_Solid( font2, "SOUND: OFF", textColor );
}
else if (!snd)
{
snd = true;
msgsnd = TTF_RenderText_Solid( font2, "SOUND: ON", textColor );
}
}
if( event.key.keysym.sym == SDLK_1 )
{
sp2lvl = 1;
msglvl = TTF_RenderText_Solid( font2, "BEGINNER", textColor );
}
if( event.key.keysym.sym == SDLK_2 )
{
sp2lvl = 2;
msglvl = TTF_RenderText_Solid( font2, "EXPERT", textColor );
}

}


if( event.type == SDL_QUIT )
{
quit = true;
bpauze = false;
}
}
}

}


I know, that my code is a mess, but this is my first SDL game and one of the first c++ app's aswell. But i hope, you can help me.
The only problems I have, as I mentioned - is getting out of pause, without any problems and when i press 's' it doesn't act like it's being held down.

Share this post


Link to post
Share on other sites
I don't have time to look over your code, but I would recommend against having a separate render/input loop for pausing the game. Just run your normal game loop, but make the game logic conditional on pause being false.

Your game loop is wrong.

There are (in general) two types of games, simulations and input-driven games. If your game is a simulation, you need to render and run the game logic regardless of whether there has been any input recently. If your game is input-driven, consider using SDL_WaitEvent() to avoid churning the processor for no reason.

And your game leaks memory at an astonishing rate.

Share this post


Link to post
Share on other sites
Thanks for all the help anyways! Which are the best articles on preventing memory leaks? I'l either start it from the beginning again, or move to breakout-ish game.

Share this post


Link to post
Share on other sites
In C++, you should learn about "Resource Aquisition Is Initialisation", or "RAII". It is the most common idiom used to manage memory. The Standard C++ Library makes extensive use of it.

Don't worry about memory leaks too much, just get your game finished for the moment, and when you start your next one keep this in mind.

Share this post


Link to post
Share on other sites

This topic is 2856 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