Skip to main content
GameDev.net gamedev.net
🔒 Locked

while key pressed

Started by raptorstrike Oct 29, 2004 at 2:57 PM 11 replies 1.6k views
Original Post
raptorstrike
raptorstrike
ok i just want to have an object move around the screen while a botton is down not every time i press it how would i code this in sdl thanks[smile]
____"This just in, 9 out of 10 americans agree that 1 out of 10 americans will disagree with the other 9"- Colin Mochrie
graveyard filla
graveyard filla
you mean a GUI style button, or a keypress, or what?

if its a keyboard, post what you have tried. it should look something like this

Uint8 *keys = SDL_GetKeyState();

if(keys[SDLK_SOMEKEY])
{
the key is pressed
}
FTA, my 2D futuristic action MMORPG
raptorstrike
raptorstrike
yeah thats what i have (sorry it took a while to get back to you) and it just dose the movment when the key is pressed not if its held down
____"This just in, 9 out of 10 americans agree that 1 out of 10 americans will disagree with the other 9"- Colin Mochrie
graveyard filla
graveyard filla
thats odd. for me it works when the key is held down. post the code that you use to take input and stuff.
FTA, my 2D futuristic action MMORPG
raptorstrike
raptorstrike
ok its pretty bare bones
#include <stdio.h>#include <stdlib.h>#include <windows.h>#include <string.h>#include <libiberty.h>#include "Ship.h"//#include "Particals.h"#include "SDL.h"/* The screen surface */SDL_Surface *screen = NULL;SDL_Surface *I_Ship = NULL;SDL_Surface *I_Exaust=NULL;SDL_Rect* Partical_rects; int SDL_Keys[5];Ship* a = new Ship;int X = 5;int Y = 5;static void draw();/* This function draws to the screen; replace this with your own code! */    intmain (int argc, char *argv[]){    Uint8 *keys = SDL_GetKeyState(SDL_Keys);    char *msg;    int done;    /* Initialize SDL */    if (SDL_Init (SDL_INIT_VIDEO) < 0)    {        asprintf (&msg, "Couldn't initialize SDL: %s\n", SDL_GetError ());        MessageBox (0, msg, "Error", MB_ICONHAND);        free (msg);        exit (1);    }    atexit (SDL_Quit);    /* Set 640x480 16-bits video mode */    screen = SDL_SetVideoMode (640, 480, 16, SDL_SWSURFACE | SDL_DOUBLEBUF);    if (screen == NULL)    {       asprintf (&msg, "Couldn't set 640x480x16 video mode: %s\n",       SDL_GetError ());        MessageBox (0, msg, "Error", MB_ICONHAND);        free (msg);        exit (2);    }    SDL_WM_SetCaption ("SDL MultiMedia Application", NULL);    I_Ship = SDL_LoadBMP("Ship.bmp");    I_Exaust = SDL_LoadBMP("Exaust.bmp");           done = 0;    while (!done)    {        SDL_Event event;        /* Check for events */        while (SDL_PollEvent (&event))        {                          switch (event.type)            {             case SDL_KEYDOWN:                                    if(keys[SDLK_UP])                    {                    a->R_Ship.x+=5;                    };                    break;            case SDL_QUIT:                done = 1;                break;            default:                break;            }        }                /* Draw to screen */        draw ();    }    return 0;}static voiddraw (){     SDL_BlitSurface(I_Ship,NULL,screen,&a->R_Ship);    SDL_Flip (screen);    /* Don't run too fast */    SDL_Delay (1);    }

thanks agin for your help [grin]
____"This just in, 9 out of 10 americans agree that 1 out of 10 americans will disagree with the other 9"- Colin Mochrie
Boku San
Boku San
I had a similar issue...try adding another case for SDL_KEYUP that will zero the x value. If that doesn't work, post again.
Things change.
Sijmen
Sijmen
Quote:
Original post by raptorstrike
ok its pretty bare bones
*** Source Snippet Removed ***
thanks agin for your help [grin]


That would be something like this.. (don't forget to look at the in-code comments).

#include <stdio.h>#include <stdlib.h>#include <windows.h>#include <string.h>#include <libiberty.h>#include "Ship.h"//#include "Particals.h"#include "SDL.h"/* The screen surface */SDL_Surface *screen = NULL;SDL_Surface *I_Ship = NULL;SDL_Surface *I_Exaust=NULL;SDL_Rect* Partical_rects; int SDL_Keys[5];Ship* a = new Ship;int X = 5;int Y = 5;static void draw();/* This function draws to the screen; replace this with your own code! */    intmain (int argc, char *argv[]){    Uint8 *keys = SDL_GetKeyState(SDL_Keys);    char *msg;    int done;    /* Initialize SDL */    if (SDL_Init (SDL_INIT_VIDEO) < 0)    {        asprintf (&msg, "Couldn't initialize SDL: %s\n", SDL_GetError ());        MessageBox (0, msg, "Error", MB_ICONHAND);        free (msg);        exit (1);    }    atexit (SDL_Quit);    /* Set 640x480 16-bits video mode */    screen = SDL_SetVideoMode (640, 480, 16, SDL_SWSURFACE | SDL_DOUBLEBUF);    if (screen == NULL)    {       asprintf (&msg, "Couldn't set 640x480x16 video mode: %s\n",       SDL_GetError ());        MessageBox (0, msg, "Error", MB_ICONHAND);        free (msg);        exit (2);    }    SDL_WM_SetCaption ("SDL MultiMedia Application", NULL);    I_Ship = SDL_LoadBMP("Ship.bmp");    I_Exaust = SDL_LoadBMP("Exaust.bmp");           done = 0;    while (!done)    {        SDL_Event event;        Uint8 *keys; // this is where we store the pressed keys        /* Check for events */        while (SDL_PollEvent (&event))        {            keys = SDL_GetKeyState(); /* get the pressed keys */            if(keys[SDLK_UP]) /* check for up */            {                a->R_Ship.x+=5; /* do something */            }               switch (event.type)            {             case SDL_QUIT:                done = 1;                break;            default:                break;            }        }                /* Draw to screen */        draw ();    }    return 0;}static voiddraw (){     SDL_BlitSurface(I_Ship,NULL,screen,&a->R_Ship);    SDL_Flip (screen);    /* Don't run too fast */    SDL_Delay (1);    }


Good luck :)

/edit:
Oh, C style comments :)
raptorstrike
raptorstrike
ok it works not it dose lag witch is kinda annoying i would normaly not mind much but seeing as this is going to be my first
A)SDL game
and
B)My first pollished game

i kinda want to avoid this so is there any way to fix this?

another note:

i think the code is getting stuck in the while loop you seggested because when i try to exit the X botton dosnt work leading me to belive that the Quit function is exicuted witch makes me think that the whole code isnt exicuted
____"This just in, 9 out of 10 americans agree that 1 out of 10 americans will disagree with the other 9"- Colin Mochrie
Boku San
Boku San
Quote:
Original post by raptorstrike
so do you want me to do this?? when you mean "seprate case"

*** Source Snippet Removed ***


Uhh...no, that's not what I meant. From the SDL documentation:

    /* Alien screen coordinates */    int alien_x=0, alien_y=0;    int alien_xvel=0, alien_yvel=0;    .    .    /* Initialise SDL and video modes and all that */    .    /* Main game loop */    /* Check for events */    while( SDL_PollEvent( &event ) ){        switch( event.type ){            /* Look for a keypress */            case SDL_KEYDOWN:                /* Check the SDLKey values and move change the coords */                switch( event.key.keysym.sym ){                    case SDLK_LEFT:                        alien_xvel = -1;                        break;                    case SDLK_RIGHT:                        alien_xvel =  1;                        break;                    case SDLK_UP:                        alien_yvel = -1;                        break;                    case SDLK_DOWN:                        alien_yvel =  1;                        break;                    default:                        break;                }                break;            /* We must also use the SDL_KEYUP events to zero the x */            /* and y velocity variables. But we must also be       */            /* careful not to zero the velocities when we shouldn't*/            case SDL_KEYUP:                switch( event.key.keysym.sym ){                    case SDLK_LEFT:                        /* We check to make sure the alien is moving */                        /* to the left. If it is then we zero the    */                        /* velocity. If the alien is moving to the   */                        /* right then the right key is still press   */                        /* so we don't tocuh the velocity            */                        if( alien_xvel < 0 )                            alien_xvel = 0;                        break;                    case SDLK_RIGHT:                        if( alien_xvel > 0 )                            alien_xvel = 0;                        break;                    case SDLK_UP:                        if( alien_yvel < 0 )                            alien_yvel = 0;                        break;                    case SDLK_DOWN:                        if( alien_yvel > 0 )                            alien_yvel = 0;                        break;                    default:                        break;                }                break;                        default:                break;        }    }    .    .    /* Update the alien position */    alien_x += alien_xvel;    alien_y += alien_yvel;


I hope that all formatted correctly. Anyway, SDL only returns ONE keypress event, the first time it's pressed.
Things change.
raptorstrike
raptorstrike
i find the Windows Key method much better (although thats one of the few things) is there any way to utalize it with SDL?

[Edited by - raptorstrike on October 30, 2004 9:27:30 PM]
____"This just in, 9 out of 10 americans agree that 1 out of 10 americans will disagree with the other 9"- Colin Mochrie
graveyard filla
graveyard filla
while boku san's method is the one your "supposed" to use, i find it difficult to use and not as flexible. this is because ALL input in your game would have to go through the polling system. this means you have to set up some sort of distributed messaging system, where you receive a keypress and then send it along to whoever needs it. while you might want to do that, i find it a hassle.

i prefer to just directly grab input from the keyboard. that is, getting input using the if(keys[SDLK_XX]) way. this way i can get input from any point in my game without using the message pump. there are 2 downsides to this:

1) you aren't guarenteed to receive all input.

2) you take input too fast.

you aren't guarenteed to receive all input. that is, on a very slow machine, you might miss some input. however, i find this to be a non serious issue. even when getting only 30 FPS, SDL still takes input WAY to fast. that is, using the "direct" method (technically its not direct, but its the best way to describe it), you would receive a button down even 10-15 times when the button was only pressed one. test it out, do something like this:

if(keys[SDLK_t])
cout << " T IS PRESSED !!! "<
when you press T, the console will print that out more then once, depending on FPS. like i said, at 30 FPS, you will probably see the print out 10-20 times. so, IMO , its nearly impossible to miss input unless your getting like 5 FPS. in which case the game isnt really worth playing anyway.

now, about the second issue. this is more serious. you take input too fast so when the key is pressed once, you might register that input 15 times. this isn't cool if you truly only wanted to do that thing 1 time and not 15 times. but, there is a pretty simple way to do it. if you look at the enginuity article here on gamedev, he talks about how to do it and shows example code, its around the 4th article in the series i believe. im not at home right now, so i cant post the code to show you, but i will whenever i get back if you want.

PS- whatcha talkin about with the windows message thing?

[Edited by - graveyard filla on October 31, 2004 12:20:07 AM]
FTA, my 2D futuristic action MMORPG
graveyard filla
graveyard filla
heres my input class. it was really easy to implement and its very very nice to have... you dont know how many timers i had set up, basically one for each keypress, well, either that or a different trick to slow down input taking. anyway, heres the header:

class Input{	public:		Input();		~Input();		void Update();		void Process_Input_Message(const SDL_Event &event);		//getting key functions		bool Cur_Key(int index) { return keys[index] != 0; }		bool Old_Key(int index) { return old_keys[index] != 0; }				bool Key_Down(int index)	{ return ( Cur_Key(index))&&(!Old_Key(index)); }		bool Key_Still_Down(int index) { return ( Cur_Key(index))&&( Old_Key(index)); }		bool Key_Up(int index) { return (!Cur_Key(index))&&( Old_Key(index)); }		bool Key_Still_Up(int index)	{ return (!Cur_Key(index))&&(!Old_Key(index)); }		//now the mouse functions		bool Cur_Mouse(int button) { return (buttons&SDL_BUTTON(button))!=0; }		bool Old_Mouse(int button) { return (old_buttons&SDL_BUTTON(button))!=0; }		bool Mouse_Down(int button) { int x,y; SDL_GetMouseState(&x,&y); if(y >= 0) return ( Cur_Mouse(button))&&(!Old_Mouse(button)); }		bool Mouse_Still_Down(int button){ return ( Cur_Mouse(button))&&( Old_Mouse(button)); }		bool Mouse_Up(int button){ return (!Cur_Mouse(button))&&( Old_Mouse(button)); }		bool Mouse_Still_Up(int button){ return (!Cur_Mouse(button))&&(!Old_Mouse(button)); }	private:		//keyboard		int key_count;		unsigned char *keys, *old_keys;		//mouse		unsigned int buttons;	    unsigned int old_buttons;};


heres the cpp:
Input::Input(){	unsigned char *temp_keys = SDL_GetKeyState(&key_count);	keys = new unsigned char [key_count];//(unsigned char*)malloc(sizeof(unsigned char) * key_count);	memcpy(keys,temp_keys,key_count);	old_keys = new unsigned char [key_count];// (unsigned char*)malloc(sizeof(unsigned char) * key_count);}void Input::Process_Input_Message(const SDL_Event &event){	switch(event.type)	{		case SDL_QUIT: 		{		}		break;		case SDL_KEYDOWN:		{		}		break;		}//end of switch event.type}void Input::Update(){	SDL_Event event;		while(SDL_PollEvent(&event))	{		Process_Input_Message(event);	}		//for keyboard	memcpy(old_keys,keys,key_count);	unsigned char *temp_keys = SDL_GetKeyState(&key_count);	memcpy(keys,temp_keys,key_count);	//for mouse  	old_buttons = buttons;	buttons = SDL_GetMouseState(NULL,NULL);}Input::~Input(){	delete [] keys;	delete [] old_keys;}


just create an Input object and call Update() each frame with it, wherever you take input normally. then you can use the functions to get mouse and keyboard input. Key_Down() means the key was _just_ pushed down. this means it will only return true the exact frame that the key was pushed, and only it will only return true one time for each key press. Key_Still_Down() will return true if a key is being held down. so, if you call this function and a key was _just_ pressed, it will return false, but if the key is still held down N number of frames (where N > 1), it will return true. the same goes for the Key_Up() functions.

the mouse functions are the same way. return true if a mouse was just clicked, or if the mouse is held down. for the mouse just send it 1,2, or 3. where 1 is left mouse click, 2 is mouse wheel pressed, and 3 is right mouse click. again, the Up() functions work the same.

also, if for some reason you pass around your Input instance by value (i dont recommend it, you should send this around by reference), you should probably make a copy constructor and = operator for the class. this is because the constructor / destructor allocates / deletes memory. if this was passed by value, the default copy constructor would be called, so the memory would never be allocated, but when it falls out of scope, the destructor would delete the memory that was never allocated, and thats when your game crash's [smile]. so, just know to always send this class by reference if you send it anywhere (like in a Get() function)
FTA, my 2D futuristic action MMORPG
raptorstrike
raptorstrike
this works great thanks alot but i noticed that with all the input stratagys ive tried SDL seems to lag is there any way to optimize this so that it lags less (THANKS AGAIN EVERY ONE [smile])

[EDIT]
actually when i call it twice a loop it dosnt lag so nvr mind thanks again

wow heres another edit your system also has no problems with multiple key presses and do you mind if i suggest this mehtod to other people (that is if you wrote it)?
____"This just in, 9 out of 10 americans agree that 1 out of 10 americans will disagree with the other 9"- Colin Mochrie

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.